Stránka 4 z 7

Re: Automatické zatváranie kurníku pre sliepky

Napsal: 30 bře 2020, 10:16
od pavel1tu
Mike_cz píše:
26 bře 2020, 08:20
No jo, to me nenapadlo. Jak jednoduche. Diky moc. Uz jsem to upravil, prevedl na minuty, a vse funguje jak ma
jeste jednou diky
Nahoď sem výsledek, díky ...
já se to snažím upravit, ale nemám ten RTC tak to nejde testovat

díky

Re: Automatické zatváranie kurníku pre sliepky

Napsal: 31 bře 2020, 13:04
od Mike_cz

Kód: Vybrat vše

/*

   ChickenDoor - V0.7
    This is modified version of the original project (https://backyardpoultry.iamcountryside.com/coops/automating-a-chicken-coop-door/).
    The original version calculated the time in seconds, this version calculates in minutes.
    
    Opens and closes a linear actuator based on sunrise and sunset tables included in the program.
    Time is in minutes

    Uses the Timezone library (url below) to automatically adjust the time twice yearly for Daylight
    Saving Time.

    

*/

// Includes
//
#include <Arduino.h>
#include <DS1307RTC.h>   //http://www.arduino.cc/playground/Code/Time
#include <Time.h>        //http://www.arduino.cc/playground/Code/Time
#include <TimeLib.h>
#include <Timezone.h>    //https://github.com/JChristensen/Timezone
#include <Wire.h>        //http://arduino.cc/en/Reference/Wire (supplied with the Arduino IDE)

#pragma GCC diagnostic ignored "-Wwrite-strings"

// Defines
//
#define DEBUG

#define OPEN     0
#define CLOSED   1
#define OFF      0
#define ON       1
#define SUNRISE_DELAY (0) //x minutes delay to open
#define SUNSET_DELAY  (30) // x minutes delay to close

// Sunset times in minutes after midnight for each ordinal day of the year,
// eg, Jan 1 = array index 0, etc. The times are CET and are adjusted one
// hour when DST is in effect.
//
// The arrays are stored in program memory because dynamic memory is not
// big enough to hold them
//
static const int sunsetAr[] PROGMEM = {965,966,968,969,970,971,972,973,975,976,977,979,980,981,983,984,986,987,989,990,992,993,995,996,998,1000,1001,1003,1005,1006,1008,
1009,1011,1012,1014,1016,1017,1019,1021,1023,1024,1026,1028,1029,1031,1033,1034,1036,1038,1039,1041,1043,1044,1046,1048,1049,1051,1052,1054,1056,
1057,1059,1060,1062,1064,1065,1067,1068,1070,1072,1073,1075,1076,1078,1079,1081,1083,1084,1086,1087,1089,1090,1092,1093,1095,1096,1098,1099,1101,1102,1104,
1106,1107,1109,1110,1112,1113,1115,1116,1118,1119,1121,1122,1124,1125,1127,1128,1130,1131,1133,1134,1136,1137,1139,1140,1142,1143,1145,1146,1148,1149,
1151,1152,1154,1155,1157,1158,1159,1161,1163,1164,1165,1167,1168,1170,1171,1172,1174,1175,1176,1178,1179,1180,1181,1182,1184,1185,1186,1187,1188,1189,1190,
1191,1192,1193,1194,1195,1196,1196,1197,1198,1198,1199,1200,1200,1201,1201,1202,1202,1202,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,1203,
1203,1202,1202,1201,1201,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,1200,
1200,1200,1200,1200,1200,1200,1200,1162,1159,1158,1157,1155,1153,1151,1150,1148,1146,1144,1142,1140,1138,1136,1134,1132,1130,1128,1110,1110,1110,1110,1110,
1110,1110,1110,1110,1090,1090,1090,1090,1090,1090,1090,1090,1090,1088,1086,1084,1082,1080,1078,1075,1073,1071,1069,1067,1065,1062,1060,1058,1056,1054,
1052,1050,1048,1045,1043,1041,1039,1037,1035,1033,1031,1029,1027,1025,1023,1021,1019,1017,1015,1013,1011,1009,1008,1006,1004,1002,1000,999,997,995,993,
992,990,989,987,985,984,982,981,980,978,977,975,974,973,972,970,969,968,967,966,965,964,963,962,962,961,960,959,959,958,
958,957,957,956,956,956,955,955,955,955,955,955,955,955,955,956,956,956,957,957,958,958,959,959,960,961,961,962,963,964,965};

static const int sunriseAr[] PROGMEM = {435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,
435,435,435,435,435,435,435,435,434,432,431,429,427,426,424,422,420,419,417,415,413,411,409,407,405,403,402,400,398,
396,394,392,390,387,385,383,381,379,377,375,373,371,369,367,364,362,360,358,356,354,352,350,347,345,343,341,339,360,300,300,
300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,300,298,296,294,292,290,288,286,284,282,281,279,277,275,273,
272,270,268,267,265,263,262,260,259,257,256,254,253,252,250,249,248,246,244,244,243,242,241,240,239,238,237,236,235,234,233,
233,232,232,231,230,230,229,229,229,228,228,228,228,228,228,228,228,228,228,228,228,228,229,229,229,230,230,231,231,232,
233,233,234,235,235,236,237,238,239,240,241,242,243,244,244,246,247,248,249,251,251,251,251,251,251,251,251,251,251,251,251,
251,251,251,251,251,251,251,251,251,251,270,270,270,270,270,270,270,270,270,270,294,296,297,299,300,300,300,300,300,300,300,
300,300,300,300,300,300,300,300,300,300,300,300,300,300,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,315,
330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,331,332,394,396,397,399,401,
402,404,405,407,409,410,412,413,415,417,418,420,421,423,425,426,428,429,431,432,434,435,435,435,435,435,435,435,435,435,
435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435,435};

// Constants
//
const int delayTime      = 1000;
const int relayOnePin    = 1;  // Unused
const int relayTwoPin    = 7;  // Door 1
const int relayThreePin  = 6;  // Door 2
const int relayFourPin   = 4;  // Lights
const int minutesPerHour = 60;

// Days of months array for ordinal calculation
static const int monthLen[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

// Globals
//
//Central European Time (Frankfurt, Paris, Prague)
TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120};     //Central European Summer Time
TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60};       //Central European Standard Time
Timezone myTZ(CEST, CET);


TimeChangeRule *tcr;        // pointer to the time change rule, use to get TZ abbrev
time_t utc, local;

int doorState = CLOSED;
int lightState = OFF;

// Init
void setup()
{
    int sunset  = 0;
    int sunrise = 0;
    int minutes = 0;

    // Initialize the relay pins
    pinMode(relayOnePin, OUTPUT);
    pinMode(relayTwoPin, OUTPUT);
    pinMode(relayThreePin, OUTPUT);
    pinMode(relayFourPin, OUTPUT);

#ifdef DEBUG
    // Start the serial port
    Serial.begin(9600);
    while (!Serial)
      ;
    delay(200);
#endif

    // Set the time using the RTC's time
    setSyncProvider(RTC.get);           // Get the time from the RTC

#ifdef DEBUG
    if(timeStatus()!= timeSet)          // Again, this is check the TZ lib status
        Serial.println("Unable to sync with the RTC");
    else
        Serial.println("RTC has set the system time ");
#endif

    // Door initialization based on TZ library time
    utc = now();
    local = myTZ.toLocal(utc, &tcr);

#ifdef DEBUG
    Serial.print("Start-up time: ");
    printTime(local, tcr -> abbrev);
#endif

    // We have the date and time, convert it to minutes since midnight
    minutes = toMinutes(hour(local), minute(local));

    // Get the ordinal day of the year to use as an index into the sunset/rise arrays
    int ordinalDay = ordinalDayOfYear(tmYearToCalendar(year(local)), month(local), day(local));

    // Get the times adjusted for DST and open/close delay
    sunrise = getAdjustedSunriseTime(ordinalDay, local);
    sunset  = getAdjustedSunsetTime(ordinalDay, local);

    // Close or open the door, the door methods check for current state
    if ((minutes > sunrise) && (minutes < sunset))
    {
       doorState = CLOSED;
       openDoor();
    } else {
       doorState = OPEN;
       closeDoor();
    }

    Serial.print(" Vychod: ");
    Serial.println(sunrise);
    Serial.print(" Zapad: ");
    Serial.println(sunset);
    Serial.print(" Aktualni: ");
    Serial.println(minutes);

}

void loop()
{
    int sunset = 0;
    int sunrise = 0;
    int minutes = 0;

    // Wait the current delay time
    delay(delayTime);

    // get current date and time
    utc = now();
    local = myTZ.toLocal(utc, &tcr);

    //Serial.print("Aktualni time: ");
    //printTime(local, tcr -> abbrev);

#ifdef DEBUG
//    printTime(local, tcr -> abbrev);
#endif

    // We have the date and time
    minutes = toMinutes(hour(local),minute(local));

    // Now get the ordinal day of the year
    int ordinalDay = ordinalDayOfYear(tmYearToCalendar(year(local)), month(local), day(local));

    // Get the times adjusted for DST and open/close delay
    sunrise = getAdjustedSunriseTime(ordinalDay, local);
    sunset  = getAdjustedSunsetTime(ordinalDay, local);

    // Close or open the door, the door methods check for current state
    if ((minutes > sunrise) && (minutes < sunset))
    {
       openDoor();
    } else {
       closeDoor();
    }

}

void openDoor()
{
    // Is the door closed?
    if (doorState == CLOSED)
    {
#ifdef DEBUG
        Serial.print("Opening door: ");
        utc = now();
        local = myTZ.toLocal(utc, &tcr);
        printTime(local, tcr -> abbrev);
#endif
        doorState = OPEN;

        // open the door
        digitalWrite(relayTwoPin, LOW);
        digitalWrite(relayThreePin, HIGH);
    }

    return;
}

void closeDoor()
{
    // Is the door open?
    if (doorState == OPEN)
    {
#ifdef DEBUG
        Serial.print("Closing door: ");
        utc = now();
        local = myTZ.toLocal(utc, &tcr);
        printTime(local, tcr -> abbrev);
#endif

        doorState = CLOSED;

        // close the door
        digitalWrite(relayTwoPin, HIGH);
        digitalWrite(relayThreePin, LOW);
    }

    return;
}


int toMinutes(int hours, int minutes)
{
    int mins = (hours*minutesPerHour)+minutes;
    return mins;
}

int ordinalDayOfYear(int year, int month, int day)
{
    int ordinal = 0;

    // Is it a leap year?
    int leap = (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0);

    // Add up the days of the months preceding the current month
    for (int i = 0; i < month - 1; i++)
    {
        ordinal += monthLen[i];
    }

    // Check for leap year
    if (leap && month > 2)
    {
        ordinal++;
    }

    // Include days in current month
    ordinal += day;

    return ordinal;
}

int getAdjustedSunriseTime(int ordinalDay, time_t local)
{
  // Get the sunrise time from the table - adjust index for zero-based array
  int sunrise = pgm_read_word_near(sunriseAr + (ordinalDay - 1));

  // Check for DST and adjust if necessary
  if (myTZ.locIsDST(local))
  {
      // Add an hour to sunrise
      sunrise += minutesPerHour;
  }
  // And finally add the sunrise opening delay
  sunrise += SUNRISE_DELAY;

  return sunrise;
}

int getAdjustedSunsetTime(int ordinalDay, time_t local)
{
  // Get the sunset time from the table - adjust index for zero-based array
  int sunset = pgm_read_word_near(sunsetAr + (ordinalDay - 1));

  // Check for DST and adjust if necessary
  if (myTZ.locIsDST(local))
  {
      // Add an hour to sunset
      sunset += minutesPerHour;
  }

  // And finally add the sunrise opening delay
  sunset += SUNSET_DELAY;

  return sunset;
}

#ifdef DEBUG

//Function to print time with time zone
void printTime(time_t t, char *tz)
{
    sPrintI00(hour(t));
    sPrintDigits(minute(t));
    sPrintDigits(second(t));
    Serial.print(' ');
    Serial.print(dayShortStr(weekday(t)));
    Serial.print(' ');
    sPrintI00(day(t));
    Serial.print(' ');
    Serial.print(monthShortStr(month(t)));
    Serial.print(' ');
    Serial.print(year(t));
    Serial.print(' ');
    Serial.print(tz);
    Serial.println();
    //delay(5000);
}

//Print an integer in "00" format (with leading zero).
//Input value assumed to be between 0 and 99.
void sPrintI00(int val)
{
    if (val < 10) Serial.print('0');
    Serial.print(val, DEC);
    return;
}

//Print an integer in ":00" format (with leading zero).
//Input value assumed to be between 0 and 99.
void sPrintDigits(int val)
{
    Serial.print(':');
    if(val < 10) Serial.print('0');
    Serial.print(val, DEC);
}

#endif
v kodu neni ta cast, ktera se tykala svetel, tu nepotrebuju. Jinak me nekamenujte, ze nejsou dodrzeny zvyklosti u psani kodu (napr. dodrzeni max. delky radku) - udelal jsem to schvalne, abych mel casy ta kazdy mesic na jedinem radku, lepe se pak hleda, pokud bude potreba upravit cas otevreni.

Re: Automatické zatváranie kurníku pre sliepky

Napsal: 01 dub 2020, 21:25
od pavel1tu
Tak já jsem potřeboval ty světla - nakonec jsem si RTC půjčil a zlomil to.
Světla svítí jen v určitém rozmezí data a času - je to v komentu a mám tam asi chybu, svítí to o hodinu déle ... ?

Má to i pár vylepšení pro ladění ....
1) pokud bude řádek DEBUG, bude to vypisovat co se děje a vypocitane hodnoty (to bylo)
- seconds - aktualni minuty od pulnoci
- sunrise a sunset - vychod a zapad slunce v minutach vyčtený z těch vasich dat

2) muzete za chodu menit cas i datum (pro ladění jestli to spíná co má)- ale zadavate čas GTM, cas na nultem poledniku, v zime -1h od nás, v lete -2h, ne aktuální čas !!! Okopírováno z projektu Budík - děkuji ....
Napisete v "Serialmonitoru" nahoře + ENTER(dodrzovat male a velke pismenka, cisla zadavat vzdy 2):
"H12" - změníte hodiny na 12h, "H02" - 2h ráno - bez tech uvozovek
"M02 - minuty na 2, "M49" - 49 minut
"d03" - den na 3.den v mesici
"m05" - měsíc na 5 měsíc v roce
"y20" - rok 2020 - nechodit pod rok 2000 !!! - já tam těch 2000 přičítám ve výpisu, a asi to i špatně uloží ...
"?" - nápověda
VŽDY změníte jen tu 1 položku, pak těch 15s čekejte
Lze použít i mimo DEBUG pro nastavení času, ale pozor je to čas GMT a nezobrazí se přepočítaný čas na naši zonu

3) cyklus lsem zpomalil na 15s - jednou za 15s to vse propocita a zobrazi - to stačí, na prasáka tam byl DELAY a ponechal jsem ho
4) vypis otvirani/zavírání a sviceni zacina "-------->" aby se to neprehledlo

PS: ten co to psal prasácky něco poskládal - ve skutečnosti se mu čas z RTC vyčte jen jednou po startu Arduina - dle mne, pak už ne.
Tak jsem to upravil.
Seconds byly dříve sekundy, teď minuty, zatím ponecháno, opravím, slibuji ;)

PS: až si to pettr vyzkouší, napíšu lepší koment + přeložím do češtiny

Kód: Vybrat vše

/*

   ChickenDoor - V0.6

    Opens and closes a linear actuator based on sunrise and sunset tables included in the program.

    Uses the Timezone library (url below) to automatically adjust the time twice yearly for Daylight
    Saving Time.

*/

// Includes
//
#include <Arduino.h>
#include <DS1307RTC.h>   //http://www.arduino.cc/playground/Code/Time
#include <Time.h>        //http://www.arduino.cc/playground/Code/Time
#include <TimeLib.h>
#include <Timezone.h>    //https://github.com/JChristensen/Timezone
#include <Wire.h>        //http://arduino.cc/en/Reference/Wire (supplied with the Arduino IDE)


//****************************************************************************************************
byte sekundy, minuty, hodiny, denVTydnu, denVmesici, mesic, rok; //global variables for time
//some chars for my use...you can add more
#define char_H 15
#define char_M 20
#define char_S 26
#define char_d 37
#define char_y 58 
//****************************************************************************************************

#pragma GCC diagnostic ignored "-Wwrite-strings"

// Defines
//
#define DEBUG    // zakomentovat PRO PROVOZ

#define OPEN     0
#define CLOSED   1
#define OFF      0
#define ON       1
#define SUNRISE_DELAY (30)
#define SUNSET_DELAY  (30)

// Sunset times in seconds after midnight for each ordinal day of the year, 
// eg, Jan 1 = array index 0, etc. The times are EST and are adjusted one
// hour when DST is in effect.
//
// The arrays are stored in program memory because dynamic memory is not
// big enough to hold them
//
static const int sunsetAr[] PROGMEM = {964,
965,966,967,968,970,971,972,973,975,976,977,979,980,982,983,985,986,988,990,992,993,995,996,999,1001,1002,1004,1006,1008,1009,1010,1012,1014,1015,1017,1019,1021,1022,1024,1026,1028,1030,1031,1033,1035,1037,
1038,1040,1042,1044,1045,1047,1049,1051,1052,1054,1056,1058,1059,1061,1063,1065,1066,1068,1070,1071,1073,1075,1076,1078,1080,1081,1083,1085,1086,1088,1090,1091,1093,1095,1096,1098,1099,1101,1103,1104,1106,
1108,1109,1111,1112,1114,1116,1117,1119,1121,1122,1124,1125,1127,1129,1130,1132,1134,1135,1137,1138,1140,1142,1143,1145,1146,1148,1150,1151,1153,1154,1156,1158,1159,1161,1162,1164,1166,1167,1169,1170,1172,
1173,1175,1176,1178,1179,1181,1182,1184,1185,1186,1188,1189,1191,1192,1193,1194,1196,1197,1198,1199,1200,1202,1203,1204,1205,1206,1207,1208,1208,1209,1210,1211,1211,1212,1213,1213,1214,1214,1216,1216,1217,1217,
1217,1217,1217,1218,1218,1218,1218,1217,1217,1217,1217,1216,1215,1215,1214,1214,1213,1213,1212,1211,1211,1210,1209,1208,1207,1206,1205,1204,1203,1202,1201,1200,1198,1197,1196,1195,1194,1193,1191,1190,1188,1186,
1184,1182,1181,1179,1177,1176,1174,1172,1170,1168,1167,1165,1163,1161,1159,1157,1155,1153,1151,1149,1147,1145,1143,1141,1139,1137,1134,1132,1130,1128,1126,1124,1121,1119,1117,1115,1113,1110,1108,1106,1104,
1101,1099,1097,1095,1093,1090,1088,1086,1083,1081,1079,1077,1074,1072,1070,1068,1065,1063,1061,1059,1057,1054,1052,1050,1048,1046,1043,1041,1039,1037,1035,1033,1031,1028,1026,1024,1022,1020,1018,1016,1014,1012,
1010,1008,1006,1004,1003,1001,999,997,995,994,992,990,988,987,985,984,982,980,979,978,976,975,973,972,971,970,968,967,966,965,964,963,962,961,960,960,959,958,957,957,956,956,955,955,955,954,954,954,954,954,
954,954,954,954,954,954,955,955,956,956,957,957,958,959,959,960,961,962,963,964};

static const int sunriseAr[] PROGMEM = {481,481,481,481,481,480,480,480,479,479,478,478,477,476,476,475,474,473,472,471,470,469,468,467,466,464,463,462,460,459,458,456,455,453,452,450,445,447,445,443,442,
440,438,436,435,433,431,429,427,425,423,421,419,417,415,413,411,409,407,405,403,401,399,396,394,392,390,388,386,383,381,379,377,375,372,370,368,366,364,361,359,357,355,352,350,348,346,344,341,339,337,335,
332,330,328,326,324,321,319,317,315,313,311,309,306,304,302,300,298,296,294,292,290,288,286,284,282,280,278,277,275,273,271,269,268,266,264,262,261,259,258,256,254,253,251,250,249,247,246,245,243,242,241,
240,239,238,237,236,235,234,233,232,231,231,230,229,229,228,228,227,227,226,226,226,226,226,226,226,226,226,226,226,226,226,227,227,227,228,228,229,229,230,231,231,232,233,234,235,235,236,237,238,239,240,241,
243,244,245,246,247,249,250,251,252,254,255,256,258,259,261,262,263,265,266,268,269,271,272,274,275,277,278,280,281,283,284,286,287,289,290,292,294,295,297,298,300,301,303,304,306,307,309,310,312,314,315,
317,318,320,321,323,324,326,327,329,330,332,334,335,337,338,340,341,343,344,346,348,349,351,352,354,355,357,359,360,362,363,365,366,368,370,371,373,375,376,378,379,381,383,384,386,388,389,391,393,394,396,
398,399,401,403,405,406,408,410,411,413,415,417,418,420,422,423,425,427,429,430,432,434,435,437,439,440,442,443,445,447,448,450,451,453,454,456,457,458,460,461,462,464,465,466,467,468,469,470,471,472,473,474,
475,476,477,477,478,478,479,480,480,480,481,481,481,481,481,481,481};

// Constants
//
const int delayTime      = 10000;
const int relayOnePin    = 1;  // Unused
const int relayTwoPin    = 2;  // Door 1
const int relayThreePin  = 3;  // Door 2
const int relayFourPin   = 4;  // Lights
const int secondsPerHour = 3600;

int sunset = 0;
int sunrise = 0;
int seconds = 0;

// Days of months array for ordinal calculation
static const int monthLen[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

// Globals
//
// Timezone rules - US Eastern Time Zone (New York, Detroit)
//TimeChangeRule myDST = {"EDT", Second, Sun, Mar, 2, -240};    //Daylight time = UTC - 4 hours
//TimeChangeRule myEST = {"EST", First, Sun, Nov, 2, -300};     //Standard time = UTC - 5 hours
//Timezone myTZ(myDST, myEST);

// Central European Time (Frankfurt, Paris)
TimeChangeRule myDST = {"CEST", Last, Sun, Mar, 2, 120}; // Central European Summer Time
TimeChangeRule myEST = {"CET ", Last, Sun, Oct, 3, 60}; // Central European Standard Time
Timezone myTZ(myDST, myEST);

TimeChangeRule *tcr;        // pointer to the time change rule, use to get TZ abbrev
time_t utc, local;

int doorState = CLOSED;
int lightState = OFF;

// Init
void setup()
{
    sunset  = 0;
    sunrise = 0;
    seconds = 0;

    // Initialize the relay pins
    pinMode(relayOnePin, OUTPUT);
    pinMode(relayTwoPin, OUTPUT);
    pinMode(relayThreePin, OUTPUT);
    pinMode(relayFourPin, OUTPUT);

    // Start the serial port
    Serial.begin(9600);
    while (!Serial)
      ;
    delay(200);


    // Set the time using the RTC's time
    setSyncProvider(RTC.get);           // Get the time from the RTC 

#ifdef DEBUG
    if(timeStatus()!= timeSet)          // Again, this is check the TZ lib status
        Serial.println("Unable to sync with the RTC");
    else
        Serial.println("RTC has set the system time "); 
#endif

    // Door initialization based on TZ library time
    utc = now();
    local = myTZ.toLocal(utc, &tcr);

    Serial.print("Start-up time: ");
    printTime(local, tcr -> abbrev);


    // We have the date and time, convert it to seconds since midnight
    seconds = toSeconds(hour(local), minute(local), 0);

    // Get the ordinal day of the year to use as an index into the sunset/rise arrays
    int ordinalDay = ordinalDayOfYear(tmYearToCalendar(year(local)), month(local), day(local));

    // Get the times adjusted for DST and open/close delay
    sunrise = getAdjustedSunriseTime(ordinalDay, local);
    sunset  = getAdjustedSunsetTime(ordinalDay, local);

    // Close or open the door, the door methods check for current state
    if ((seconds > sunrise) && (seconds < sunset))
    {
       doorState = CLOSED;
       openDoor();
    } else {
       doorState = OPEN;
       closeDoor();
    }

    // Turn the lights on (6AM) or off (9PM)
    initCoopLights(local);

//****************************************************************************************************
  //COMMUNICATION
  //Wire.begin(); //start I2C communication
  Serial.println(F(""));
  Serial.println(F("H = hour, M = minute,y = year, m = month, d = day "));
  Serial.println(F("H20  M07  y20  m04  d01  = 20:07   1.4.2020"));
  Serial.println(F(""));
  Serial.println(F("Aktualni cas a datum v RTC modulu"));
  vypis();
//****************************************************************************************************    
}

void loop()
{
    //**************************************************************************************************** 
    SerialComm();
    tmElements_t tm;
    RTC.read(tm);
    //**************************************************************************************************** 
    setSyncProvider(RTC.get);
    
    sunset = 0;
    sunrise = 0;
    seconds = 0;
    
    // Wait the current delay time
    delay(delayTime);

    // get current date and time
    utc = now();
    local = myTZ.toLocal(utc, &tcr);



    // We have the date and time
    seconds = toSeconds(hour(local), minute(local), 0);

    // Now get the ordinal day of the year
    int ordinalDay = ordinalDayOfYear(tmYearToCalendar(year(local)), month(local), day(local));

    // Get the times adjusted for DST and open/close delay
    sunrise = getAdjustedSunriseTime(ordinalDay, local);
    sunset  = getAdjustedSunsetTime(ordinalDay, local);

    // Close or open the door, the door methods check for current state
    if ((seconds > sunrise) && (seconds < sunset))
    {
       openDoor();
    } else {
       closeDoor();
    }

    // Turn the lights on (6AM) or off (9PM)
    setCoopLights(local);

#ifdef DEBUG
    printTime(local, tcr -> abbrev);
    Serial.print("seconds=");
    Serial.print(seconds);
    Serial.print(" - sunrise=");
    Serial.print(sunrise);
    Serial.print(" - sunset=");
    Serial.print(sunset);
    Serial.println("");
#endif    
}

void openDoor()
{
    // Is the door closed?
    if (doorState == CLOSED)
    {
#ifdef DEBUG
        Serial.print("-----> Opening door: ");    
        utc = now();
        local = myTZ.toLocal(utc, &tcr);
        printTime(local, tcr -> abbrev);
#endif
        doorState = OPEN;

        // open the door
        digitalWrite(relayTwoPin, HIGH);
        digitalWrite(relayThreePin, HIGH);
    }

    return;
}

void closeDoor()
{
    // Is the door open?
    if (doorState == OPEN)
    {
#ifdef DEBUG
        Serial.print("-----> Closing door: ");    
        utc = now();
        local = myTZ.toLocal(utc, &tcr);
        printTime(local, tcr -> abbrev);
#endif
            
        doorState = CLOSED;

        // close the door
        digitalWrite(relayTwoPin, LOW);
        digitalWrite(relayThreePin, LOW);
    }

    return;
}

void initCoopLights(time_t t)
{
  int curHour = hour(t);
  int curDen = day(t);
  int curMesic = month(t);

  // Rosvitit po zapadu slunce do 20h ve dnech 5.10. do cca 15.3. pokud jsou zavrena dvirka
    if (seconds > sunset-60 && curHour < 21 && (curMesic *100 + curDen  >= 1005  || curMesic *100 + curDen <= 315) )
  {
      // Turn on the lights
      lightState = ON;
#ifdef DEBUG
  Serial.print("-----> Turning lights on: ");
  utc = now();
  local = myTZ.toLocal(utc, &tcr);
  printTime(local, tcr -> abbrev);
#endif      
      digitalWrite(relayFourPin, LOW);
  } else {

      // Turn off the lights
      lightState = OFF;
#ifdef DEBUG
  Serial.print("-----> Turning lights off: ");
  utc = now();
  local = myTZ.toLocal(utc, &tcr);
  printTime(local, tcr -> abbrev);
#endif      
      digitalWrite(relayFourPin, HIGH);
  }

  return;
}

void setCoopLights(time_t t)
{
  int curHour = hour(t);
  int curDen = day(t);
  int curMesic = month(t);

  // Rosvitit po zapadu slunce do 20h ve dnech 5.10. do cca 15.3. pokud jsou zavrena dvirka
    if (seconds > sunset-60 && curHour < 21 && (curMesic *100 + curDen  >= 1005  || curMesic *100 + curDen <= 315) )
  {
    if (lightState == OFF)
    {
#ifdef DEBUG
  Serial.print("-----> Turning lights on at ");
  Serial.println(curHour);
#endif
      lightState = ON;
      
      // Turn off the lights
      digitalWrite(relayFourPin, LOW);
    }
  } else {
    if (lightState == ON)
    {
      lightState = OFF;
#ifdef DEBUG
  Serial.print("-----> Turning lights off at ");
  Serial.println(curHour);
#endif       
      // Turn on the lights
      digitalWrite(relayFourPin, HIGH);
    }  
  }

  return;
}

int toSeconds(int hours, int minutes, int seconds)
{
    int secs = (hours*60)+(minutes);
    return secs;
}

int ordinalDayOfYear(int year, int month, int day)
{
    int ordinal = 0;

    // Is it a leap year?
    int leap = (year % 4 == 0) && (year % 100 != 0 || year % 400 == 0);

    // Add up the days of the months preceding the current month
    for (int i = 0; i < month - 1; i++)
    {
        ordinal += monthLen[i];
    }

    // Check for leap year
    if (leap && month > 2)
    {
        ordinal++;
    }

    // Include days in current month
    ordinal += day;

    return ordinal;
}

int getAdjustedSunriseTime(int ordinalDay, time_t local)
{
  // Get the sunrise time from the table - adjust index for zero-based array
  int sunrise = pgm_read_word_near(sunriseAr + (ordinalDay - 1));

  // Check for DST and adjust if necessary
  if (myTZ.locIsDST(local))
  {
      // Add an hour to sunrise
      sunrise += 60;
  }
  // And finally add the sunrise opening delay
  sunrise += SUNRISE_DELAY;
  
  return sunrise;
}

int getAdjustedSunsetTime(int ordinalDay, time_t local)
{
  // Get the sunset time from the table - adjust index for zero-based array
  int sunset = pgm_read_word_near(sunsetAr + (ordinalDay - 1));

  // Check for DST and adjust if necessary
  if (myTZ.locIsDST(local))
  {
      // Add an hour to sunset
      sunset += 60;
  }

  // And finally add the sunrise opening delay
  sunset += SUNSET_DELAY;

  return sunset;
}



//Function to print time with time zone
void printTime(time_t t, char *tz)
{
    sPrintI00(hour(t));
    sPrintDigits(minute(t));
    sPrintDigits(second(t));
    Serial.print(' ');
    Serial.print(dayShortStr(weekday(t)));
    Serial.print(' ');
    sPrintI00(day(t));
    Serial.print(' ');
    Serial.print(monthShortStr(month(t)));
    Serial.print(' ');
    Serial.print(year(t));
    Serial.print(' ');
    Serial.print(tz);
    Serial.println();
}

//Print an integer in "00" format (with leading zero).
//Input value assumed to be between 0 and 99.
void sPrintI00(int val)
{
    if (val < 10) Serial.print('0');
    Serial.print(val, DEC);
    return;
}

//Print an integer in ":00" format (with leading zero).
//Input value assumed to be between 0 and 99.
void sPrintDigits(int val)
{
    Serial.print(':');
    if(val < 10) Serial.print('0');
    Serial.print(val, DEC);
}




//serial communication with PC
void SerialComm() {
  tmElements_t tm;
  //first char - data type
  //sekundy and third char - data value
  //there are used only "printable" characters

  if (Serial.available() > 0) {
    byte receivedCommand;
    receivedCommand = Serial.read();  //read first char

    delay(10);  //wait for other char

    byte receivedDataTens;
    receivedDataTens = Serial.read();
    receivedDataTens -= 48; // ASCII code for "0" is 48

    byte receivedDataOnes;
    receivedDataOnes = Serial.read();
    receivedDataOnes -= 48; // ASCII code for "0" is 48

    byte receivedData;
    receivedData = (receivedDataTens * 10) + receivedDataOnes;
    if (receivedData > 99) {
      //maximal value is 99
      receivedData = 0; //value is out of range
    }
    switch (receivedCommand) {

    case 72:
      //hodiny 72 = H
      if (receivedData > 23) {
        receivedData = 23;
      }
      tm.Hour = receivedData;
      RTC.write(tm);
      vypis();
      break;

    case 77:
      //minuty 77 = M
      if (receivedData > 59) {
        receivedData = 59;
      }
      tm.Minute = receivedData;
      RTC.write(tm);
      vypis();
      break;
      
    case 83:
      //sekundy 83 = S
      if (receivedData > 59) {
        receivedData = 59;
      }
      tm.Second = receivedData;
      RTC.write(tm);
      vypis();
      break;
      
    case 100:
      //denVmesici 100 = d
      if (receivedData > 31) {
        receivedData = 1;
      }
      tm.Day = receivedData;
      RTC.write(tm);
      vypis();
      break;
  
    case 109:
      //mesic 109 = m
      if (receivedData > 12) {
        receivedData = 1;
      }
      tm.Month = receivedData;
      RTC.write(tm);
      vypis();
      break;

    case 121:
      //rok 121 = y
      tm.Year = receivedData + 2000;
      RTC.write(tm);
      vypis();
      break;
    case 63:
      //get data ? = 63
      Serial.println(F(""));
      Serial.println(F("H = hodiny, M = minuty,y = rok, m = mesic, d = day "));
      Serial.println(F("H20  M07  y20  m04  d01  = 20:07   1.4.2020"));
      Serial.println(F(""));      
      break;
    }
    //flush serial data
    Serial.flush();
  }
}

void vypis() {
tmElements_t tm;

  if (RTC.read(tm)) {
    Serial.print("Ok, GMT Time = ");
    print2digits(tm.Hour);
    Serial.write(':');
    print2digits(tm.Minute);
    Serial.write(':');
    print2digits(tm.Second);
    Serial.print(", Date (D/M/Y) = ");
    Serial.print(tm.Day);
    Serial.write('/');
    Serial.print(tm.Month);
    Serial.write('/');
    Serial.print(tmYearToCalendar(tm.Year));
    Serial.println();
      } else {
    if (RTC.chipPresent()) {
      Serial.println("The DS1307 is stopped.  Please run the SetTime");
      Serial.println("example to initialize the time and begin running.");
      Serial.println();
    } else {
      Serial.println("DS1307 read error!  Please check the circuitry.");
      Serial.println();
    }
    
  }
     
}

void print2digits(int number) {
  if (number >= 0 && number < 10) {
    Serial.write('0');
  }
  Serial.print(number);
}

Re: Automatické zatváranie kurníku pre sliepky

Napsal: 26 dub 2020, 21:23
od Dadasys
Ahojte vespolek, staví se další kurník..
pořeboval bych poradit s úpravou kódu, aby odečítání z fotorezistoru proběhlo jednou za 5 minut. Resp. jde o to, že zvětšení delay na třetím řádku způsobí, že těch pět minut nespínají koncová čidla. Kde hledat chybku? Máte někdo radu pro začátečníka, co s tím? D :)

Kód: Vybrat vše

void loop() {
  systemState = 0;
  delay (1000); // měření po 1 sec
  photocellVal = analogRead(photocellPin); // read inputs
  if (photocellVal > daythreshold)
  {
    daylight = true;
  }
  if (photocellVal < darkthreshold)
  {
    daylight = false;
  }
  topSwitchState = digitalRead(topSwitchPin);
  bottomSwitchState = digitalRead(bottomSwitchPin);
  //  read system status
  if (daylight == true && topSwitchState == true)
  {
    systemState = 0;   // motor stoji
  }
  if (daylight == true && topSwitchState == false)
  {
    systemState = 1;  // dvere se oteviraji
  }
  if (daylight == false && bottomSwitchState == true)
  {
    systemState = 0;    // motor stoji
  }
  if (daylight == false && bottomSwitchState == false)
  {
    systemState = 2;  // dvere se zaviraji
  }
  DispVals();
  switch (systemState) {
    case 0: // motor stoji
      digitalWrite(CloseDoorPin, LOW);
      digitalWrite(OpenDoorPin, LOW);
      analogWrite(EnMotorPin, 0);
      break;
    case 1:  // dvere se oteviraji
      digitalWrite(CloseDoorPin, LOW);
      digitalWrite(OpenDoorPin, HIGH);
      analogWrite(EnMotorPin, SPEED);
      break;
    case 2:  // dvere se zaviraji
      digitalWrite(CloseDoorPin, HIGH);
      digitalWrite(OpenDoorPin, LOW);
      analogWrite(EnMotorPin, SPEED);
      break;
    default:
      digitalWrite(CloseDoorPin, LOW);
      digitalWrite(OpenDoorPin, LOW);
      analogWrite(EnMotorPin, 0);
      break;
  }
}

Re: Automatické zatváranie kurníku pre sliepky

Napsal: 27 dub 2020, 05:45
od Axamith
Příkaz delay() je pro podobné projekty zlo.
Ulož si aktuální millis() a podmínkou prověř měření v čase + požadovaná perioda.

Re: Automatické zatváranie kurníku pre sliepky

Napsal: 27 dub 2020, 06:11
od pavel1tu
S někým jsem řešil kurník po e-mailu,
tak se koukněte jak je to řešené a zkuste použít ...

Kód: Vybrat vše

#define light 11                    //vystup pro zarovku
#define rele_open 12                //vystup pro rele otevrit
#define rele_close 13               //vystup pro rele zavrit
#define light_sens A0               //analog pro pripojeni senzoru svetla

#define time_light 13               // hodiny - cas konce doby sviceni od svitani

#define ladeni 0                    // 0 - ladeni      1 - bez vystupu na Seriovy port

#if (ladeni)
#define cyklus 5                    // sekundy - cyklus mereni pro ladeni
#else
#define cyklus 15                   // sekundy - jak casto probehne task mereni
#endif

// *********************** nize uz nic nemenit *****************************************
int is,im,ih,id,ida;                // variables for time
float time,s1,m1,h1,d1, light2;     //  Set up variables to calculate time
bool state = false, casujeme = false;
 
unsigned long aktualniMillis, predchoziMillis;  //casy pro 15s task mereni
unsigned long ranoMillis;                       //ulozeny cas pri vychodu slunce pro casovani 13h

const unsigned long SECOND = 1000;
#if (ladeni)
const unsigned long HOUR = 60000;               //ladeni = napevno 1 minuta misto hodiny
#else
const unsigned long HOUR = 3600*SECOND;
#endif

void setup(){
  pinMode (light_sens, INPUT);  
  pinMode (light, OUTPUT);  
  pinMode (rele_open, OUTPUT);  
  pinMode (rele_close, OUTPUT);  
 
  Serial.begin(9600);

  predchoziMillis = millis();                   //cas startu arduina
}

void loop(){
  aktualniMillis = millis();                             //aktualni cas behu arduina
  
  if(aktualniMillis - predchoziMillis > cyklus * 1000) {         //task probihajici jednou za XXs
     predchoziMillis = aktualniMillis;                   //nulovani XXs citace
     
     if(ladeni) Serial.println(analogRead(light_sens));  //namerena hodnota senzoru
     if(ladeni) Serial.println(state);                   //aktualni stav

     if(analogRead(light_sens) >= 550 && state == false){   //uz je svetlo a state = FALSE
        state = true;
        digitalWrite(rele_close, LOW);   
        digitalWrite(rele_open, HIGH);                    //otevrit dvirka 
        ranoMillis = millis();                            //zacatek casu pro 13h 
        casujeme = true;
        if(ladeni) Serial.println("Otevrit");                                   
        }

     if(analogRead(light_sens) <= 200 && state == true){   //podminka pro rozsviceni
        digitalWrite(light, HIGH);                        //rozsvitit
        if(ladeni) Serial.println("Rozsvitit");
        }

     if(analogRead(light_sens) <= 100 && state == true){   //podminka pro zavreni dvirek
        state = false;
        digitalWrite(rele_open, LOW);   
        digitalWrite(rele_close, HIGH);                   //zavrit dvirka
        if(ladeni) Serial.println("Zavrit");
        }
                                                          //zhasnout za X hodin
     if(aktualniMillis - ranoMillis > time_light * HOUR && casujeme == true) {    
        digitalWrite(light, LOW);
        casujeme = false;
        if(ladeni) Serial.println("Zhasnout");
     }

     
  } //konec tasku po 15s
 
}   //konec LOOP


Re: Automatické zatváranie kurníku pre sliepky

Napsal: 27 dub 2020, 09:30
od Dadasys
Díky pánové, zkusím tedy prošťouchnout millis..
D

Odesláno z mého Lenovo P2a42 pomocí Tapatalk


Re: Automatické zatváranie kurníku pre sliepky

Napsal: 27 dub 2020, 10:04
od pavel1tu
Dadasys píše:
27 dub 2020, 09:30
Díky pánové, zkusím tedy prošťouchnout millis..
D

Odesláno z mého Lenovo P2a42 pomocí Tapatalk
Když bude problém, příští týden to sfouknem s dětmi na kroužku, teď jsem zasekanej.

Re: Automatické zatváranie kurníku pre sliepky

Napsal: 29 dub 2020, 22:10
od Dadasys
Tak metodou pokus jsem něco dopsal a zdá se, že to funguje. Díky za posrtčení.

Kód: Vybrat vše



const long eventTime_1_LDR = 20000; // 20 vteřin
unsigned long previousTime_1 = 0;

int photocellVal;            // analog reading of the photocel

bool daylight = true;        // daylight status
int darkthreshold = 20;
int daythreshold = 350;      

int systemState = 0;
int SPEED = 220;

int bottomSwitchPin = 2;  // Reed switches top and bottom of coop door
int topSwitchPin = 4;

bool topSwitchState; // true if door is up
bool bottomSwitchState; // true if door is down

void setup() {

  Serial.begin(9600);
  pinMode(bottomSwitchPin, INPUT);
  pinMode(topSwitchPin, INPUT);
  pinMode(EnMotorPin, OUTPUT);
  pinMode(CloseDoorPin, OUTPUT);
  pinMode(OpenDoorPin, OUTPUT);
  
}

void loop() {
  systemState = 0;
    unsigned long currentTime = millis();
    if ( currentTime - previousTime_1 >= eventTime_1_LDR) {
    photocellVal = analogRead(photocellPin); // read inputs
    previousTime_1 = currentTime;
  }

  if (photocellVal > daythreshold)

  {
    daylight = true;
  
  
atd..

Re: Automatické zatváranie kurníku pre sliepky

Napsal: 30 dub 2020, 08:31
od pavel1tu
Skvělé,
je to paráda, když to člověk zlomí, že ?

Kdyby něco, klidně napište ...