Automatické zatváranie kurníku pre sliepky

Nedaří se vám s projektem a nenašli jste vhodné místo, kde se zeptat? Napište sem.
Pravidla fóra
Tohle subfórum je určeno pro konzultaci ucelených nápadů, popřípadě řešení komplexnějších projektů, které opravdu není možné rozdělit na menší části.
Většinu problémů jde rozdělit na menší a ptát se na ně v konkrétních subfórech.
Odpovědět
Uživatelský avatar
pavel1tu
Příspěvky: 2054
Registrován: 26 říj 2017, 08:28
Reputation: 0
Bydliště: Trutnov
Kontaktovat uživatele:

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

Příspěvek od pavel1tu » 30 bře 2020, 10:16

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
UNO, NANO, Mikro, PRO mini, DUE, ESP32S2, RPi PICO
Pavel1TU
"Správně napsaný kod lze číst jako knihu"

Mike_cz
Příspěvky: 11
Registrován: 02 říj 2017, 13:15
Reputation: 0

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

Příspěvek od Mike_cz » 31 bře 2020, 13:04

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.

Uživatelský avatar
pavel1tu
Příspěvky: 2054
Registrován: 26 říj 2017, 08:28
Reputation: 0
Bydliště: Trutnov
Kontaktovat uživatele:

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

Příspěvek od pavel1tu » 01 dub 2020, 21:25

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);
}
UNO, NANO, Mikro, PRO mini, DUE, ESP32S2, RPi PICO
Pavel1TU
"Správně napsaný kod lze číst jako knihu"

Dadasys
Příspěvky: 18
Registrován: 17 dub 2020, 14:52
Reputation: 0

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

Příspěvek od Dadasys » 26 dub 2020, 21:23

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;
  }
}

Axamith
Příspěvky: 530
Registrován: 09 srp 2017, 08:17
Reputation: 0
Kontaktovat uživatele:

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

Příspěvek od Axamith » 27 dub 2020, 05:45

Příkaz delay() je pro podobné projekty zlo.
Ulož si aktuální millis() a podmínkou prověř měření v čase + požadovaná perioda.

Uživatelský avatar
pavel1tu
Příspěvky: 2054
Registrován: 26 říj 2017, 08:28
Reputation: 0
Bydliště: Trutnov
Kontaktovat uživatele:

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

Příspěvek od pavel1tu » 27 dub 2020, 06:11

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

UNO, NANO, Mikro, PRO mini, DUE, ESP32S2, RPi PICO
Pavel1TU
"Správně napsaný kod lze číst jako knihu"

Dadasys
Příspěvky: 18
Registrován: 17 dub 2020, 14:52
Reputation: 0

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

Příspěvek od Dadasys » 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


Uživatelský avatar
pavel1tu
Příspěvky: 2054
Registrován: 26 říj 2017, 08:28
Reputation: 0
Bydliště: Trutnov
Kontaktovat uživatele:

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

Příspěvek od pavel1tu » 27 dub 2020, 10:04

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.
UNO, NANO, Mikro, PRO mini, DUE, ESP32S2, RPi PICO
Pavel1TU
"Správně napsaný kod lze číst jako knihu"

Dadasys
Příspěvky: 18
Registrován: 17 dub 2020, 14:52
Reputation: 0

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

Příspěvek od Dadasys » 29 dub 2020, 22:10

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..

Uživatelský avatar
pavel1tu
Příspěvky: 2054
Registrován: 26 říj 2017, 08:28
Reputation: 0
Bydliště: Trutnov
Kontaktovat uživatele:

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

Příspěvek od pavel1tu » 30 dub 2020, 08:31

Skvělé,
je to paráda, když to člověk zlomí, že ?

Kdyby něco, klidně napište ...
UNO, NANO, Mikro, PRO mini, DUE, ESP32S2, RPi PICO
Pavel1TU
"Správně napsaný kod lze číst jako knihu"

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 11 hostů