First sketch look over

My first sketch is finally at what I think is a usable stage. I know there is probably much better ways to do things, but I didnt want to user code I didnt understand, which limited me. I'll refine it as I learn, but are there any glaring mistakes that will bite me? Basically it opens a chicken coop door and slowly brightens the coop lights at sunrise. It slowly dims the lights 14 hours later and shuts the coop door at sunset.

I exported a table of sunset sunrise times at -5 from UDT, so I wouldnt have to deal with daylight saving time. I am a little unclear on the progmem syntax, but I copied that part, and it appears to work correctly.

#include "RTClib.h"
RTC_DS3231 rtc;

int brightness = 40;
int day = 31;
int month = 12;
int minutes;
int dayofyear = 0;
int dimmer = 3;
int relay1 = 4;
int relay2 = 8;

// Sunrise minutes from midnight. Daylight savings time ignored.
static const long sunriseAr[] PROGMEM = {
446,447,447,447,447,447,447,447,447,446,446,446,446,446,445,445,444,444,444,443,443,442,
442,441,440,440,439,438,437,437,436,435,434,433,432,431,430,429,428,427,426,425,424,423,
422,420,419,418,417,416,414,413,412,410,409,408,406,405,404,402,401,399,398,396,395,393,
392,391,389,388,386,384,383,381,380,378,377,375,374,372,371,369,368,366,365,363,361,360,
358,357,355,354,352,351,349,348,346,345,343,342,340,339,337,336,334,333,332,330,329,328,
326,325,323,322,321,320,318,317,316,315,313,312,311,310,309,308,307,306,305,304,303,302,
301,300,299,298,297,296,296,295,294,293,293,292,291,291,290,290,289,289,288,288,288,287,
287,287,286,286,286,286,286,286,286,285,285,285,286,286,286,286,286,286,286,287,287,287,
288,288,288,289,289,290,290,291,291,292,292,293,293,294,295,295,296,296,297,298,299,299,
300,301,302,302,303,304,305,306,306,307,308,309,310,311,311,312,313,314,315,316,317,318,
318,319,320,321,322,323,324,325,326,326,327,328,329,330,331,332,333,333,334,335,336,337,
338,339,340,340,341,342,343,344,345,346,346,347,348,349,350,351,352,353,353,354,355,356,
357,358,359,360,360,361,362,363,364,365,366,367,368,369,369,370,371,372,373,374,375,376,
377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,
399,401,402,403,404,405,406,407,408,409,410,411,413,414,415,416,417,418,419,420,421,422,
423,424,425,426,427,428,429,430,431,432,433,433,434,435,436,437,437,438,439,440,440,441,
441,442,443,443,444,444,444,445,445,445,446,446,446,446};

// Sunset minutes from midnight. Daylight savings time ignored.
static const long sunsetAr[] PROGMEM = {
1020,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,
1037,1038,1039,1040,1041,1043,1044,1045,1046,1047,1048,1049,1051,1052,1053,1054,1055,1056,
1057,1058,1060,1061,1062,1063,1064,1065,1066,1067,1068,1070,1071,1072,1073,1074,1075,1076,
1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,
1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1110,1111,
1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1125,1126,1127,1128,
1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1141,1142,1143,1144,1145,
1146,1147,1148,1149,1150,1151,1152,1153,1153,1154,1155,1156,1157,1158,1159,1159,1160,1161,
1162,1163,1163,1164,1165,1166,1166,1167,1168,1168,1169,1170,1170,1171,1171,1172,1172,1173,
1173,1174,1174,1175,1175,1175,1176,1176,1176,1176,1177,1177,1177,1177,1177,1177,1177,1177,
1177,1177,1177,1177,1177,1176,1176,1176,1176,1175,1175,1175,1174,1174,1173,1173,1172,1172,
1171,1170,1170,1169,1168,1168,1167,1166,1165,1164,1164,1163,1162,1161,1160,1159,1158,1157,
1156,1155,1153,1152,1151,1150,1149,1148,1146,1145,1144,1143,1141,1140,1139,1137,1136,1134,
1133,1132,1130,1129,1127,1126,1124,1123,1121,1120,1118,1117,1115,1114,1112,1111,1109,1108,
1106,1105,1103,1102,1100,1098,1097,1095,1094,1092,1090,1089,1087,1086,1084,1083,1081,1079,
1078,1076,1075,1073,1072,1070,1069,1067,1066,1064,1062,1061,1060,1058,1057,1055,1054,1052,
1051,1049,1048,1047,1045,1044,1043,1041,1040,1039,1038,1036,1035,1034,1033,1032,1030,1029,
1028,1027,1026,1025,1024,1023,1022,1021,1021,1020,1019,1018,1017,1017,1016,1015,1015,1014,
1013,1013,1012,1012,1012,1011,1011,1010,1010,1010,1010,1009,1009,1009,1009,1009,1009,1009,
1009,1009,1009,1009,1010,1010,1010,1010,1011,1011,1012,1012,1012,1013,1013,1014,1015,1015,
1016,1017,1017,1018,1019,1019};

void setup () {

   Serial.begin(57600);

#ifndef ESP8266
  while (!Serial); // wait for serial port to connect. Needed for native USB
#endif

  if (! rtc.begin()) {
    Serial.flush();
    abort();
  }

rtc.adjust(DateTime(2020, 1, 1, 7, 25, 30)); // spoof time for testing
  
pinMode(relay1, OUTPUT);
pinMode(relay2, OUTPUT);
pinMode(dimmer, OUTPUT);
digitalWrite (relay1, LOW);
digitalWrite (relay2, LOW);  
analogWrite(dimmer,0);
 
  DateTime now = rtc.now(); 
  while(day > 1 || month > 1){
  DateTime dayb4 (now - TimeSpan(dayofyear,0,0,0));
  month = dayb4.month();
  day = dayb4.day();
  dayofyear++;
  }dayofyear--; // Subtract 1 day due to tables staring at 0
}

void loop() { 
  DateTime now = rtc.now();
  // increments 1 day forward at midmight. Delays 90 minutes during inactive period. 
  if (now.hour() == 0){
    dayofyear++;
    delay(90*60*1000UL);
  }
  
  // Get the sunrise sunset times from the tables
  long rise = pgm_read_word_near(sunriseAr + (dayofyear));
  long set = pgm_read_word_near(sunsetAr + (dayofyear));
  int lightoff = rise + 840; // Minutes after midnight that lights begin to dim.

  Serial.print(dayofyear, DEC);
  Serial.println(rise, DEC);
  Serial.println(set, DEC);
  Serial.println(lightoff, DEC);
  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(" (");
  Serial.print(") ");
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println();
  
  minutes = now.hour() * 60 + now.minute(); // minutes after midnight

  if(minutes >= rise &&  minutes < set)
  {
   digitalWrite (relay1, HIGH);
   digitalWrite (relay2, HIGH);
       
    if(minutes == rise){
      brightness = 40;
      while(brightness<200)
      {
        analogWrite(dimmer,brightness);
        delay(500);
        brightness++;
      }
    rtc.adjust(DateTime(2020, 1, 1, 16, 59, 30)); // spoof time for testing
    }
  }

  if(minutes > lightoff)
  {
    while(brightness>40)
    {
      analogWrite(dimmer,brightness);
      delay(500);
      brightness--;
      
      // Closes door if sunset occurs while lights are dimming. 
      DateTime now = rtc.now();
      minutes = now.hour() * 60 + now.minute(); // minutes after midnight
            
      if(minutes >= set)
      {
       digitalWrite (relay1, LOW);
       digitalWrite (relay2, LOW);  
      }
    }
  analogWrite(dimmer,0);
  }
  
  if(minutes >= set)
  {
   digitalWrite (relay1, LOW);
   digitalWrite (relay2, LOW);       
  }
delay(1000);
}

Daylight savings time is never a problem if you keep your main clock running UTC.

I know that would have been the better way to do it, but sunset here on a number of days was the next day UTC. I had several ideas on how to resolve it, but just said screw it this time around and the clock can stay -5:) I'll learn more and do a better sketch, as long as this one function for awhile.

In many cases, if you are confident that you have a working sketch, it's better to move on. You can always try different stuff later.

You use type int to hold values that type byte will hold, like pin numbers.

You use type long to hold values that type int will hold.

   if(minutes == rise){
      brightness = 40;
      while(brightness<200)
      {
        analogWrite(dimmer,brightness);
        delay(500);
        brightness++;
      }
    rtc.adjust(DateTime(2020, 1, 1, 16, 59, 30)); // spoof time for testing
    }

I admit I didn't read the entire sketch, but this caught my eye. Isn't this going to run for an entire minute? Unless there is some state change detection, minutes==rise will pass as many times through loop as happen in one minute. In that case, the dimming will pulse over and over.

It incrementally brightens from 40 to 200 with 500ms sleep between each increment. About 80 seconds, so it only hits the loop once. The delays in all the lighting loops will be increased significantly, so light changes occur over about an hour.

I added a line to bump the time forward 30 seconds on each loop for testing. Running through the whole year. If no glitches, I think I trust it.

++Karma: //Well done on getting your first project working!

My pet hate is delay, and you use a lot of delay in your code. Delay means nothing else is happening or can happen. Nothing happening in your current project may well be perfectly OK and work fine, but it will be a headache for more advanced projects.

Before your next project study these and work out how to use them in your own code.
Using millis for timing
Demonstration for several things at the same time

I'm impressed that you managed to encode into your project a year's worth of sunrise and sunset times, that must have given you sore fingers! I can't help thinking you could have simplifies this by a factor of 7 by only using times for 1 day of the week, not all 7. The small error that would have given would probably not have mattered. Also, if noon is 12:00 then the sunrise and sunset times are roughly symmetrical about noon, so that halves the data you have to enter as long as you don't need the accuracy of having the exact times.

Most likely if you come back to this project after doing some others and learning you will see loads of things you can improve that are not at all obvious at the moment.

Thanks! I read some about millis. I need to learn a lot more.

In my day job, I use a lot powershell for sys admin type stuff. For the time tables, I was able to download the year from the net, save as a csv,
remove dst and calculate minutes with powershell.