Control acuario (luz, temperatura y oxigenación)

Hola a todos.
Este es mi primer post, y aunque os sigo desde hace 2 o 3 años y me he leído las normas del foro y de como postear, seguramente me habré equivocado en alguna cosa, por lo que pido disculpas de antemano.
Hace 2 años me sumergí por primera vez en programación y electrónica con Arduino sin casi saber nada, con la intención de controlar algunos parámetros de un acuario de agua dulce de 60 litros, y con mucho orgullo de novato hoy puedo compartirlo. Lo tengo funcionando sin interrupción des de hace más de 1 año sin fallos significativos, aunque cada pocos meses se produce algún cuelgue que todavía estoy intentando resolver.
Estaré encantado de recibir propuestas de mejora y optimización del código.

El software controla:
Iluminación: La luz del acuario se enciende y se apaga sincronizada con el amanecer y el ocaso real, simulando intensidades diferentes cada día y pasando por el azul, rojo y blanco. La intensidad de la luz de luna va sincronizada con la fase real de la luna.
Temperatura: Durante todo el año la temperatura se mantiene entre 24 y 25 grados controlando 2 ventiladores y 1 calentador en función de los valores de 1 sonda de temperatura.
Oxigenación: El Oxigenador se enciende durante las horas diurnas y se apaga por la noche.
Pantalla Oled: Para mostrar los valores que interesen en cada momento.

El material utilizado para este proyecto ha sido:
General:

  • 1 Arduino Starter Kit con ARDUINO UNO REV 3
  • 1 Transformador a 5V - DC5V Switch LED Power Supply Transformers10A
  • 1 Placa de expansión ZHITING Proto Screw Shield V2
  • Placa de Circuito Impreso Snappable ElectroCookie

Para la estructura:

  • 4 Enchufes Simon F1590443030 con Toma de Tierra Serie 15 Blanco
  • 5 Conector jack estéreo hembra 3,5 mm
  • 5 Audio Conector TRS Macho Plug 3 Polos 1/8" 3.5mm
  • 1 Conector IEC C14 Chasis Macho 10A 250V 3 pines NEGRO
  • Espaciadores Separador FTVOGUE 120 Unids M3 Macho Hembra
  • Una caja de madera del Chino
  • Un metacrilato

Para control de tiempo:

  • 1 Reloj en tiempo real AZDelivery Modulo RTC DS3231 y bateria incluida I2C

Para la pantalla de datos:

  • 1 Modulo Pantalla AZDelivery OLED Display I2C 128 x 64 pixeles 0.96

Para la pantalla de luces: (casera)

  • Tira Led SK6812 RGBW 4 in 1 Pixels Individual Addressable Led Strip DC5V
  • Pines BTF-LIGHTING JST SM 3 Connectors For WS2812B WS2811 WS2812 LED Strip Female Male
  • 5 Canales de aluminio LED en forma de V (5 unidades, 1 m, perfil de aluminio con cubierta)

Para el control de Temperatura y Oxigenación:

  • 1 Sensor de Temperatura AZDelivery 2 x 1m Cable DS18B20
  • 2 Ventiladores ELUTENG USB Doble 12cm Fan Portatil 5V 0.3A con Parrilla de metal
  • 1 Módulo de Controlador MOSFET IRF520
  • 2 Modulo Rele AZDelivery 5 pcs 1 Canal KY-019 5V High-Level-Trigger
  • Calentador de acuario
  • Oxigenador de acuario

Muchas gracias

Adjunto:

  • El código:
#include <Adafruit_NeoPixel.h>      // Incluye libreria para control Leds SK6812 RGBW (Admin. Librerias)
#include <Wire.h>                   // Incluye libreria para RELOJ DS3231 (Admin. Librerias)
#include <RTClib.h>                 // Incluye libreria para RELOJ DS3231 (Admin. Librerias)
#include <Dusk2Dawn.h>              // Incluye libreria Dusk2Dawn para calculo de salida y ocaso (https://github.com/dmkishi/Dusk2Dawn)
#include <TimeLord.h>               // Incluye libreria TIMELORD para calculo de FASE LUNAR (https://github.com/probonopd/TimeLord/find/master)
#include <OneWire.h>                // Incluye libreria DS18B20  para control de temperatura (Admin. Librerias)
#include <DallasTemperature.h>      // Incluye libreria DS18B20 para control de temperatura (Admin. Librerias)
#include <U8g2lib.h>                // Incluye libreria para control de pantalla OLED 128X64 0,96 (https://github.com/olikraus/u8g2/blob/master/cppsrc/U8g2lib.h)
#define LED_PIN 6                   // Config Pin leds
#define NUMPIXELS 168               // Config Num Pixels
#define ventiladoresPin 4           // Config Pin ventiladores
#define calentadorPin 5             // Config Pin Calentador
#define oxigenacionPin 7            // Config Pin Oxigenador

Adafruit_NeoPixel tira = Adafruit_NeoPixel(NUMPIXELS, LED_PIN, NEO_GRBW + NEO_KHZ800);   // Config Leds SK6812 RGBW
RTC_DS3231 rtc;                                                                          // Config Leds RELOJ DS3231
OneWire ourWirePin1(2);                                                                  // Config Pin sonda temperatura DS18B20
DallasTemperature sensors1(&ourWirePin1);                                                // Config Pin sonda temperatura DS18B20
DeviceAddress address1 = {0x28, 0x6A, 0x1A, 0xE3, 0x22, 0x20, 0x1, 0x56};                // dirección sonda temperatura DS18B20
U8G2_SSD1306_128X64_NONAME_2_SW_I2C u8g2 (U8G2_R0, A3, A2);                              // Config Pin pantalla OLED 128X64 0,96

bool ventiladoresEstado = false;                                                                                                // Variable para estado Ventiladors
bool calentadorEstado = false;                                                                                                  // Variable para estado calentador
bool oxigenacionEstado = false;                                                                                                 // Variable para estado Oxigeno
int i = -1, i1 = -2, i2 = -3, j = 0;                                                                                            // Variable para control de pixels
int pixelsTots = NUMPIXELS * 2, pixelsMeitat = NUMPIXELS, pixelsTer = NUMPIXELS * 2 / 3;                                        // Variable para control de pixels
int var = 0;                                                                                                                    // Variable Leds
boolean cambio = true;                                                                                                          // Variable  Leds
byte intensitatLluna = 255, intensitatVermOcaso = 100, intensitatVermAlbada = 100, intensitatBlau = 100, intensitatBlanc = 255; // Variables intensidad leds
float latitud = 41.403521, longitud = 2.174440;                                                                                 // Definimos posición para calcular salida y ocaso de sol
int var1 = 0;                                                                                                                   // Variable pantalla Oled
float tempVentOn = 25.5, tempVentOff = 25.0, tempCalentOn = 24, tempCalentOff = 24.5;                                           // Definimos temperaturas
unsigned long millisAbansPrint, millisAbansTemp, millisAra;                                                                     //  MILLIS Y TIEMPO -Definimos todas las variables de tiempo que necesitaremos
unsigned long millisAraPrint, millisAraTemp, millisAbans;
unsigned long intervalFade = 900000, intervalFade2 = intervalFade / NUMPIXELS, intervalFadeMin = ((intervalFade / 1000) / 60);

char diaAraPrint[16];                                                                                                           // Variables de 16 caracteres para impresion en pantalla Oled
char horaAraPrint[16];
char hora1Print[16];
char hora3Print[16];
char hora8Print[16];
char hora12Print[16];

void setup() {
  rtc.begin();                                            // Inicia RELOJ DS3231
  // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));      // Usar para poner en hora la primera vez o con cambio de pila
  tira.begin();                                           // Inicia Leds SK6812 RGBW
  tira.clear();                                           // Limpia Leds SK6812 RGBW
  tira.fill(tira.Color(0, 0, 250, 0));                    // Establece Leds SK6812 RGBW en azul a 250 de intensidad
  tira.show();                                            // Muestra Leds SK6812 RGBW
  pinMode (ventiladoresPin, OUTPUT);                      // Config  ventiladores
  sensors1.begin();                                       // Inicia Sonda de temperatura
  pinMode( calentadorPin, OUTPUT);                        // Config  calentador
  pinMode( oxigenacionPin, OUTPUT);                       // Config Oxigenación
  pinMode(A2, OUTPUT);                                    // Config OLED 128X64 0,96
  digitalWrite(A2, 0);
  u8g2.begin();                                           // Inicia pantalla Oled
  u8g2.setPowerSave(0);
  u8g2.setFont(u8g2_font_ncenB10_tr);                     // Establece formato de letra
}

void loop() {
  DateTime now = rtc.now();                                                             // RELLOTGE DS3231 -Toma la fecha y hora actual
  int tempsAraMin = ((now.hour() * 60) + now.minute());                                 // Transforma la hora a minutos totales
  Dusk2Dawn Barcelona(latitud, longitud, 2);                                            // Establece posicion y calcula hora de salida del sol.cambiar 1 hinvierno o 2 verano al cambiar hora
  int crvSunrise  = Barcelona.sunrise(now.year(), now.month(), now.day(), false);       //  Calcula salida del sol
  // int crvSunrise = 582; // (usar para hacer pruebas i anular el anterior
  TimeLord tardis;
  tardis.Position(latitud, longitud);                                                   // Establece posición para calculo de fase lunar
  byte today[] = {  0, 0, 12, now.day(), now.month(), 21};                              // Establece dia para calculo de fase lunar
  float  phase = tardis.MoonPhase(today);                                               // Establece fase lunar
  float phase2 = 1 - phase;                                                             // Valor para calculo de intensidad de luna segun fase lunar

  /****************Establece intensidad de luz Lunar segun fase Lunar***************************/
  if (phase <= 0.50) {
    intensitatBlau = (phase * 2) * intensitatLluna;
  }
  else {
    intensitatBlau = (phase2 * 2) * intensitatLluna;
  }

  /*Usar para hacer pruebas
    int hora1 = crvSunrise;// true
    int hora2 = crvSunrise + intervalFadeMin + 1;//5 false
    int hora3 = crvSunrise + ((intervalFadeMin * 2) + 2);//10 true
    int hora4 = crvSunrise + ((intervalFadeMin * 3) + 3);//15 false
    int hora5 = crvSunrise + ((intervalFadeMin * 4) + 4);//20 true
    int hora6 = crvSunrise + ((intervalFadeMin * 5) + 5);//25 false
    int hora7 = crvSunrise + ((intervalFadeMin * 6) + 6);//30 true
    int hora8 = crvSunrise + ((intervalFadeMin * 7) + 7);//35 false
    int hora9 = crvSunrise + ((intervalFadeMin * 8) + 8);//40 true
    int hora10 = crvSunrise + ((intervalFadeMin * 9) + 9);//45 false
    int hora11 = crvSunrise + ((intervalFadeMin * 10) + 10);//50 true
    int hora12 = crvSunrise + ((intervalFadeMin * 11) + 11);//55 false
    int hora13 = crvSunrise + ((intervalFadeMin * 12) + 12);//55 false
  */
  /***************************Encendido de Leds para horari de verano**************************

    int hora1 = crvSunrise;                                               //                    Inici Llum Lluna
    int hora2 = crvSunrise + (intervalFadeMin + 1);                       //+16 min             Inici Albada vermella
    int hora3 = crvSunrise + ((intervalFadeMin * 2) + 2);                 //+32 min             Sortida del Sol 1
    int hora4 = crvSunrise + ((intervalFadeMin * 3) + 3);                 //+48 min             Sortida del Sol 2
    int hora5 = crvSunrise + ((intervalFadeMin * 4) + 4);                 //+64 min             Sortida del Sol 3
    int hora6 = crvSunrise + 240;                                         //+4 hores            Sol a zenit
    int hora7 = crvSunrise + 540;                                         //+9 hores            Sol down
    int hora8 = crvSunrise + 620;                                         //+10 hores           Inici Posta de sol
    int hora9 = (crvSunrise + 620 ) + (intervalFadeMin + 1);              //+10:16 hores        Llum de lluma 1
    int hora10 = (crvSunrise + 620 ) + ((intervalFadeMin * 2) + 2);       //+10:32 hores        Llum de lluma 2
    int hora11 = (crvSunrise + 620 ) + ((intervalFadeMin * 3) + 3);       //+10:48 hores        Llum de lluna 3
    int hora12 = crvSunrise + 900;                                        //+15 hores           Fosc
    int hora13 = (crvSunrise + 900 ) + (intervalFadeMin + 1);
  */
  /***************************Encendido de Leds para horari de otoño***************************/

  int hora1 = crvSunrise - ((intervalFadeMin * 3) + 3);                 //-48 min             Inici Llum Lluna
  int hora2 = crvSunrise - ((intervalFadeMin * 2) + 2);                 //-32 min             Inici Albada vermella
  int hora3 = crvSunrise - (intervalFadeMin + 1);                       //-16 min             Sortida del Sol 1
  int hora4 = crvSunrise;                                               //                    Sortida del Sol 2
  int hora5 = crvSunrise + (intervalFadeMin + 1);                       //+16 min             Sortida del Sol 3
  int hora6 = crvSunrise + 180;                                         //+4 hores            Sol a zenit
  int hora7 = crvSunrise + 540;                                         //+9 hores            Sol down
  int hora8 = crvSunrise + 620;                                         //+10 hores           Inici Posta de sol
  int hora9 = (crvSunrise + 620 ) + (intervalFadeMin + 1);              //+10:16 hores        Llum de lluma 1
  int hora10 = (crvSunrise + 620 ) + ((intervalFadeMin * 2) + 2);       //+10:32 hores        Llum de lluma 2
  int hora11 = (crvSunrise + 620 ) + ((intervalFadeMin * 3) + 3);       //+10:48 hores        Llum de lluna 3
  int hora12 = crvSunrise + 900;                                        //+15 hores           Fosc
  int hora13 = (crvSunrise + 900 ) + (intervalFadeMin + 1);

  /*************************** Encendido de Leds para horario de hinvierno***************************
    int hora1 = crvSunrise - ((intervalFadeMin * 3) + 3);                 //-48 min             Inici Llum Lluna
    int hora2 = crvSunrise - ((intervalFadeMin * 2) + 2);                 //-32 min             Inici Albada vermella
    int hora3 = crvSunrise - (intervalFadeMin + 1);                       //-16 min             Sortida del Sol 1
    int hora4 = crvSunrise;                                               //                    Sortida del Sol 2
    int hora5 = crvSunrise + (intervalFadeMin + 1);                       //+16 min             Sortida del Sol 3
    int hora6 = crvSunrise + 180;                                         //+3 hores            Sol a zenit
    int hora7 = crvSunrise + 480;                                         //+8 hores            Sol down
    int hora8 = crvSunrise + 540;                                         //+9 hores            Inici Posta de sol
    int hora9 = (crvSunrise + 540 ) + (intervalFadeMin + 1);              //+9:16 hores         Llum de lluma 1
    int hora10 = (crvSunrise + 540 ) + ((intervalFadeMin * 2) + 2);       //+9:32 hores         Llum de lluma 2
    int hora11 = (crvSunrise + 540 ) + ((intervalFadeMin * 3) + 3);       //+9:48 hores         Llum de lluna 3
    int hora12 = crvSunrise + 780;                                        //+13 hores           Fosc
    int hora13 = (crvSunrise + 780 ) + (intervalFadeMin + 1);
  */

  /**************** Medición de Temperatura i encendido de Calentador o ventiladores*****************/
  sensors1.requestTemperatures();                                         // Se envía el comando para leer la temperatura
  float temp1 = sensors1.getTempC(address1);                              // Se obtiene la temperatura en ºC
  if (ventiladoresEstado == false && (temp1 > tempVentOn)) {              // VENTILADOR - CALENTADOR Si temp >26 refrijera hasta 25 - Si Temp <23.5 calienta hasta 24.5
    ventiladoresEstado = true;
    digitalWrite(ventiladoresPin, HIGH);
  }
  else if (ventiladoresEstado == true && (temp1 < tempVentOff)) {
    ventiladoresEstado = false;
    digitalWrite(ventiladoresPin, LOW);
  }
  if (calentadorEstado == false && (temp1 < tempCalentOn)) {
    calentadorEstado = true;
    digitalWrite(calentadorPin, HIGH);
  }
  else if (calentadorEstado == true && (temp1 > tempCalentOff)) {
    calentadorEstado = false;
    digitalWrite(calentadorPin, LOW);
  }

  /***************************Encendido y apagado de oxigenacion***************************/
  if (oxigenacionEstado == false && ((tempsAraMin >= hora1) && (tempsAraMin < hora12))) {
    oxigenacionEstado = true;
    digitalWrite(oxigenacionPin, HIGH);
  }
  else if (oxigenacionEstado == true && ((tempsAraMin < hora1)  || (tempsAraMin > hora12))) {
    oxigenacionEstado = false;
    digitalWrite(oxigenacionPin, LOW);
  }


  /*************************** Imprime en pantalla Oled***************************/
  sprintf(diaAraPrint, "%02d/%02d/%02d", now.day(), now.month(), now.year());
  sprintf(horaAraPrint, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
  sprintf(hora1Print, "%02d:%02d", (hora1 / 60), (hora1 - ((hora1 / 60) * 60)));
  sprintf(hora3Print, "%02d:%02d", (hora2 / 60), (hora2 - ((hora2 / 60) * 60)));
  sprintf(hora8Print, "%02d:%02d", (hora8 / 60), (hora8 - ((hora8 / 60) * 60)));
  sprintf(hora12Print, "%02d:%02d", (hora12 / 60), (hora12 - ((hora12 / 60) * 60)));

  millisAraPrint = millis();
  while (var1 <= 1) {
    millisAbansPrint = millis();
    var1++;
  }

  if (millisAraPrint - millisAbansPrint < 4000) {

    u8g2.firstPage();
    do {
      u8g2.clearBuffer();
      u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.setCursor(0, 15);
      u8g2.print(diaAraPrint);
      u8g2.setCursor(0, 35);
      u8g2.print(horaAraPrint);
      u8g2.setCursor(0, 60);
      u8g2.print(F("Temp: "));
      u8g2.print(temp1);
    } while ( u8g2.nextPage() );
  }

  else if ((millisAraPrint - millisAbansPrint > 4000) && (millisAraPrint - millisAbansPrint < 8000)) {

    u8g2.firstPage();
    do {
      u8g2.clearBuffer();
      u8g2.setFont(u8g2_font_ncenB12_tr);
      u8g2.setCursor(0, 15);
      u8g2.print(F("Ll:  "));
      u8g2.print(hora1Print);
      u8g2.print("  ");
      u8g2.print(intensitatVermAlbada);
      u8g2.setCursor(0, 30);
      u8g2.print(F("Al:  "));
      u8g2.print(hora3Print);
      u8g2.print("  ");
      u8g2.print(intensitatBlanc);
      u8g2.setCursor(0, 45);
      u8g2.print(F("Ps:  "));
      u8g2.print(hora8Print);
      u8g2.print("  ");
      u8g2.print(intensitatVermOcaso);
      u8g2.setCursor(0, 60);
      u8g2.print(F("Fs:  "));
      u8g2.print(hora12Print);
      u8g2.print("  ");
      u8g2.print(intensitatBlau);
    } while ( u8g2.nextPage() );
  }
  else if (millisAraPrint - millisAbansPrint > 8000) {
    var1 = 0;
  }

  /*************************** Encendido i apagado de Luces segun hora***************************/
  if ((tempsAraMin >= hora1) && (tempsAraMin <= hora2)) {
    if (cambio == true) {
      amanecerAzul();
    }
  }
  else if ((tempsAraMin >= hora2) && (tempsAraMin <= hora3)) {
    if (cambio == false) {
      amanecerRojo();
    }
  }
  else if ((tempsAraMin >= hora3) && (tempsAraMin <= hora4)) {
    if (cambio == true) {
      amanecerBlanco1();
    }
  }
  else if ((tempsAraMin >= hora4) && (tempsAraMin <= hora5)) {
    if (cambio == false) {
      amanecerBlanco2();
    }
  }
  else if ((tempsAraMin >= hora5) && (tempsAraMin <= hora6)) {
    if (cambio == true) {
      amanecerBlanco3();
    }
  }
  else if ((tempsAraMin >= hora6) && (tempsAraMin <= hora7)) {
    if (cambio == false) {
      solZenitUp();
    }
  }
  else if ((tempsAraMin >= hora7) && (tempsAraMin <= hora8)) {
    if (cambio == true) {
      solZenitDown();
    }
  }
  else if ((tempsAraMin >= hora8) && (tempsAraMin <= hora9)) {
    if (cambio == false) {
      ocasoRojo();
    }
  }
  else if ((tempsAraMin >= hora9) && (tempsAraMin <= hora10)) {
    if (cambio == true) {
      ocasoAzul1();
    }
  }
  else if ((tempsAraMin >= hora10) && (tempsAraMin <= hora11)) {
    if (cambio == false) {
      ocasoAzul2();
    }
  }
  else if ((tempsAraMin >= hora11) && (tempsAraMin <= hora12)) {
    if (cambio == true) {
      ocasoAzul3();
    }
  }
  else if ((tempsAraMin >= hora12) && (tempsAraMin <= hora13)) {
    if (cambio == false) {
      lunaZenitDown();
    }
  }
}

/********************************* AMANECER AZUL LEDS SK6812 RGBW*********************************
   Se encienden los leds uno a uno con incremento de intensidad.
   El brillo es proporcional a la fase de la luna real en la posicion establecida:
   Luna nueva intensidad 0 hasta Luna llena intensidad 255
*/
void amanecerAzul() {
  while (var <= 2) {
    intensitatVermAlbada = random(25, 255);
    intensitatVermOcaso = random(25, 255);
    intensitatBlanc = random(100, 255);
    var++;
  }
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / pixelsTots)) {
    millisAbans = millisAra;
    if (i < NUMPIXELS) {
      i++;
    }
    else {
      i = -1;
      cambio = false;
      var = 0;
    }
    for (int j = 0; j < intensitatBlau; j++) {
      tira.setPixelColor(i, tira.Color(0, 0, j, 0));
      tira.show();
    }
  }
}


/*********************************** AMANECER ROJO LEDS SK6812 RGBW***********************************
   Se encienden los leds uno si uno no con incremento de intensidad.
   El brillo cambia cada dia y es aleatorio entre 25 y 255 para simular amaneceres mas o menos rojizos
*/
void amanecerRojo() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsMeitat))) {
    millisAbans = millisAra;
    if (i < NUMPIXELS) {
      i = i + 2;
    }
    else {
      i = -1;
      cambio = true;
    }
    for (int j = 0; j < intensitatVermAlbada; j++) {
      tira.setPixelColor(i, tira.Color(j, 0, 0, 0));
      tira.show();
    }
  }
}
/* **********************************AMANECER BLANCO LEDS SK6812 RGBW***********************************
   Se encienden los leds uno de cada 3 con incremento de intensidad.
   Hay 3 fases de encendido. La primera fase enciende a partir del Led 0, la segunda del Led 1 y la tercera del Led 2
   Finaliza con todos los Leds encendidos en intensidad 100
*/
void amanecerBlanco1() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTer))) {
    millisAbans = millisAra;
    if (i2 < NUMPIXELS) {
      i2 = i2 + 3;
    }
    else {
      i2 = -3;
      cambio = false;
    }
    for (int j = 0; j < 100; j++) {
      tira.setPixelColor(i2, tira.Color(0, 0, 0, j));
      tira.show();
    }
  }
}
void amanecerBlanco2() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTer))) {
    millisAbans = millisAra;
    if (i1 < NUMPIXELS) {
      i1 = i1 + 3;
    }
    else {
      i1 = -2;
      cambio = true;
    }
    for (int j = 0; j < 100; j++) {
      tira.setPixelColor(i1, tira.Color(0, 0, 0, j));
      tira.show();
    }
  }
}
void amanecerBlanco3() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTer))) {
    millisAbans = millisAra;
    if (i < NUMPIXELS) {
      i = i + 3;
    }
    else {
      i = -1;
      cambio = false;
    }
    for (int j = 0; j < 100; j++) {
      tira.setPixelColor(i, tira.Color(0, 0, 0, j));
      tira.show();
    }
  }
}
/*********************************** LUZ DE SOL DIA BLANCO LEDS SK6812 RGBW****************************
   Se encienden los leds uno a uno con incremento de intensidad.
   El brillo cambia cada dia y es aleatorio entre 100 y 255 para simular dias de nubes o de pleno sol
*/
void solZenitUp() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTots))) {
    millisAbans = millisAra;
    if (i < NUMPIXELS) {
      i++;
    }
    else {
      i = -1;
      cambio = true;
    }
    for (int j = 100; j < intensitatBlanc; j++) {
      tira.setPixelColor(i, tira.Color(0, 0, 0, j));
      tira.show();
    }
  }
}
/************************************LUZ DE SOL TARDE BLANCO LEDS SK6812 RGBW**********************
   Disminuye la intensidad de los leds uno a uno hasta 100 para simular la tarde
*/
void solZenitDown() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTots))) {
    millisAbans = millisAra;
    if (i < NUMPIXELS) {
      i++;
    }
    else {
      i = -1;
      cambio = false;
    }
    for (int j = intensitatBlanc; j >= 100; j--) {
      tira.setPixelColor(i, tira.Color(0, 0, 0, j));
      tira.show();
    }
  }
}
/*********************************** OCASO ROJO LEDS SK6812 RGBW***********************************
   Se encienden los leds uno si uno no con incremento de intensidad.
   El brillo cambia cada dia y es aleatorio entre 25 y 255 para simular ocasos mas o menos rojizos
*/
void ocasoRojo() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsMeitat))) {
    millisAbans = millisAra;
    if (i < NUMPIXELS) {
      i = i + 2;
    }
    else {
      i = -1;
      cambio = true;
    }
    for (int j = 0; j < intensitatVermOcaso; j++) {
      tira.setPixelColor(i, tira.Color(j, 0, 0, 0));
      tira.show();
    }
  }
}
/************************************ OCASO AZUL LEDS SK6812 RGBW***********************************
   Se encienden los leds uno de cada 3 con incremento de intensidad.
   Hay 3 fases de encendido. La primera fase enciende a partir del Led 0, la segunda del Led 1 y la tercera del Led 2
   Finaliza con todos los Leds encendidos en intensidad de luz proporcional a la fase de la Luna
*/
void ocasoAzul1() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTer))) {
    millisAbans = millisAra;
    if (i2 < NUMPIXELS) {
      i2 = i2 + 3;
    }
    else {
      i2 = -3;
      cambio = false;
    }
    for (int j = 0; j < intensitatBlau; j++) {
      tira.setPixelColor(i2, tira.Color(0, 0, j, 0));
      tira.show();
    }
  }
}
void ocasoAzul2() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTer))) {
    millisAbans = millisAra;
    if (i < NUMPIXELS) {
      i = i + 3;
    }
    else {
      i = -1;
      cambio = true;
    }
    for (int j = 0; j < intensitatBlau; j++) {
      tira.setPixelColor(i, tira.Color(0, 0, j, 0));
      tira.show();
    }
  }
}
void ocasoAzul3() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTer))) {
    millisAbans = millisAra;
    if (i1 < NUMPIXELS) {
      i1 = i1 + 3;
    }
    else {
      i1 = -2;
      cambio = false;
    }
    for (int j = 0; j < intensitatBlau; j++) {
      tira.setPixelColor(i1, tira.Color(0, 0, j, 0));
      tira.show();
    }
  }
}
/********************************* APAGADO LUZ DE LUNA AZUL LEDS SK6812 RGBW*********************************
   Se apagan los leds uno a uno con intensidad decreciente
*/
void lunaZenitDown() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTots))) {
    millisAbans = millisAra;
    if (i < NUMPIXELS) {
      i++;
    }
    else {
      i = -1;
      cambio = true;
    }
    for (int j = intensitatBlau; j >= 0; j--) {
      tira.setPixelColor(i, tira.Color(0, 0, j, 0));
      tira.show();
      tira.clear();
    }
  }
}

Hola @Gertru buena presentación y desarrollo de tu proyecto.
A modo de complemento y tal vez este de mas publico el código (tu código) para una lectura mas rápida ya que buscas consejos, comentarios de como optimizar el mismo.

#include <Adafruit_NeoPixel.h>                                                                                                  //Incluye libreria para control Leds SK6812 RGBW
#include <Wire.h>                                                                                                               //Incluye libreria para RELOJ DS3231
#include <RTClib.h>                                                                                                             //Incluye libreria para RELOJ DS3231
#include <Dusk2Dawn.h>                                                                                                          //Incluye libreria Dusk2Dawn para calculo de salida y ocaso
#include <TimeLord.h>                                                                                                           //Incluye libreria TIMELORD para calculo de FASE LUNAR 
#include <OneWire.h>                                                                                                            //Incluye libreria DS18B20  para control de temperatura 
#include <DallasTemperature.h>                                                                                                  //Incluye libreria DS18B20 para control de temperatura
#include <U8g2lib.h>                                                                                                            //Incluye libreria para control de pantalla OLED 128X64 0,96
#define LED_PIN 6                                                                                                               //Config Pin leds
#define NUMPIXELS 168                                                                                                           //Config Num Pixels
#define ventiladoresPin 4                                                                                                       //Config Pin ventiladores
#define calentadorPin 5                                                                                                         //Config Pin Calentador
#define oxigenacionPin 7                                                                                                        //Config Pin Oxigenador

Adafruit_NeoPixel tira = Adafruit_NeoPixel(NUMPIXELS, LED_PIN, NEO_GRBW + NEO_KHZ800);                                          //Config Leds SK6812 RGBW
RTC_DS3231 rtc;                                                                                                                 //Config Leds RELOJ DS3231
OneWire ourWirePin1(2);                                                                                                         //Config Pin sonda temperatura DS18B20
DallasTemperature sensors1(&ourWirePin1);                                                                                       //Config Pin sonda temperatura DS18B20
DeviceAddress address1 = {0x28, 0x6A, 0x1A, 0xE3, 0x22, 0x20, 0x1, 0x56};                                                       //dirección sonda temperatura DS18B20
U8G2_SSD1306_128X64_NONAME_2_SW_I2C u8g2 (U8G2_R0, A3, A2);                                                                     //Config Pin pantalla OLED 128X64 0,96

bool ventiladoresEstado = false;                                                                                                //Variable para estado Ventiladors
bool calentadorEstado = false;                                                                                                  //Variable para estado calentador
bool oxigenacionEstado = false;                                                                                                 //Variable para estado Oxigeno
int i = -1, i1 = -2, i2 = -3, j = 0;                                                                                            //Variable para control de pixels
int pixelsTots = NUMPIXELS * 2, pixelsMeitat = NUMPIXELS, pixelsTer = NUMPIXELS * 2 / 3;                                        //Variable para control de pixels
int var = 0;                                                                                                                    //Variable Leds
boolean cambio = true;                                                                                                          //Variable  Leds
byte intensitatLluna = 255, intensitatVermOcaso = 100, intensitatVermAlbada = 100, intensitatBlau = 100, intensitatBlanc = 255; //Variables intensidad leds
float latitud = 41.403521, longitud = 2.174440;                                                                                 //Definimos posición para calcular salida y ocaso de sol
int var1 = 0;                                                                                                                   //Variable pantalla Oled
float tempVentOn = 25.5, tempVentOff = 25.0, tempCalentOn = 24, tempCalentOff = 24.5;                                           //Definimos temperaturas                       
unsigned long millisAbansPrint, millisAbansTemp, millisAra;                                                                     // MILLIS Y TIEMPO -Definimos todas las variables de tiempo que necesitaremos.
unsigned long millisAraPrint, millisAraTemp, millisAbans;
unsigned long intervalFade = 900000, intervalFade2 = intervalFade / NUMPIXELS, intervalFadeMin = ((intervalFade / 1000) / 60);

char diaAraPrint[16];                                                                                                           //Variables de 16 caracteres para impresion en pantalla Oled
char horaAraPrint[16];
char hora1Print[16];
char hora3Print[16];
char hora8Print[16];
char hora12Print[16];

void setup() {
  rtc.begin();                                                                                                                  //Inicia RELOJ DS3231
  //rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));                                                                             //Usar para poner en hora la primera vez o con cambio de pila
  tira.begin();                                                                                                                 //Inicia Leds SK6812 RGBW
  tira.clear();                                                                                                                 //Limpia Leds SK6812 RGBW
  tira.fill(tira.Color(0, 0, 250, 0));                                                                                          //Establece Leds SK6812 RGBW en azul a 250 de intensidad
  tira.show();                                                                                                                  //Muestra Leds SK6812 RGBW
  pinMode (ventiladoresPin, OUTPUT);                                                                                            //Config  ventiladores
  sensors1.begin();                                                                                                             //Inicia Sonda de temperatura
  pinMode( calentadorPin, OUTPUT);                                                                                              //Config  calentador
  pinMode( oxigenacionPin, OUTPUT);                                                                                             //Config Oxigenación
  pinMode(A2, OUTPUT);                                                                                                          //Config OLED 128X64 0,96
  digitalWrite(A2, 0);
  u8g2.begin();                                                                                                                 //Inicia pantalla Oled
  u8g2.setPowerSave(0);
  u8g2.setFont(u8g2_font_ncenB10_tr);                                                                                           //Establece formato de letra
}

void loop() {
  DateTime now = rtc.now();                                                                                                     //RELLOTGE DS3231 -Toma la fecha y hora actual
  int tempsAraMin = ((now.hour() * 60) + now.minute());                                                                         //Transforma la hora a minutos totales
  Dusk2Dawn Barcelona(latitud, longitud, 2);                                                                                    //Establece posicion y calcula hora de salida del sol.cambiar 1 hinvierno o 2 verano al cambiar hora
  int crvSunrise  = Barcelona.sunrise(now.year(), now.month(), now.day(), false);                                               // Calcula salida del sol
  //int crvSunrise = 582; //(usar para hacer pruebas i anular el anterior
  TimeLord tardis;
  tardis.Position(latitud, longitud);                                                                                           //Establece posición para calculo de fase lunar
  byte today[] = {  0, 0, 12, now.day(), now.month(), 21};                                                                      //Establece dia para calculo de fase lunar
  float  phase = tardis.MoonPhase(today);                                                                                       //Establece fase lunar
  float phase2 = 1 - phase;                                                                                                     //Valor para calculo de intensidad de luna segun fase lunar

  /****************Establece intensidad de luz Lunar segun fase Lunar***************************/
  if (phase <= 0.50) {
    intensitatBlau = (phase * 2) * intensitatLluna;
  }
  else {
    intensitatBlau = (phase2 * 2) * intensitatLluna;
  }

  /* Usar para hacer pruebas
  int hora1 = crvSunrise;// true
  int hora2 = crvSunrise + intervalFadeMin + 1;//5 false
  int hora3 = crvSunrise + ((intervalFadeMin * 2) + 2);//10 true
  int hora4 = crvSunrise + ((intervalFadeMin * 3) + 3);//15 false
  int hora5 = crvSunrise + ((intervalFadeMin * 4) + 4);//20 true
  int hora6 = crvSunrise + ((intervalFadeMin * 5) + 5);//25 false
  int hora7 = crvSunrise + ((intervalFadeMin * 6) + 6);//30 true
  int hora8 = crvSunrise + ((intervalFadeMin * 7) + 7);//35 false
  int hora9 = crvSunrise + ((intervalFadeMin * 8) + 8);//40 true
  int hora10 = crvSunrise + ((intervalFadeMin * 9) + 9);//45 false
  int hora11 = crvSunrise + ((intervalFadeMin * 10) + 10);//50 true
  int hora12 = crvSunrise + ((intervalFadeMin * 11) + 11);//55 false
  int hora13 = crvSunrise + ((intervalFadeMin * 12) + 12);//55 false

  /***************************Encendido de Leds para horari de verano**************************

    int hora1 = crvSunrise;                                               //                    Inici Llum Lluna
    int hora2 = crvSunrise + (intervalFadeMin + 1);                       //+16 min             Inici Albada vermella
    int hora3 = crvSunrise + ((intervalFadeMin * 2) + 2);                 //+32 min             Sortida del Sol 1
    int hora4 = crvSunrise + ((intervalFadeMin * 3) + 3);                 //+48 min             Sortida del Sol 2
    int hora5 = crvSunrise + ((intervalFadeMin * 4) + 4);                 //+64 min             Sortida del Sol 3
    int hora6 = crvSunrise + 240;                                         //+4 hores            Sol a zenit
    int hora7 = crvSunrise + 540;                                         //+9 hores            Sol down
    int hora8 = crvSunrise + 620;                                         //+10 hores           Inici Posta de sol
    int hora9 = (crvSunrise + 620 ) + (intervalFadeMin + 1);              //+10:16 hores        Llum de lluma 1
    int hora10 = (crvSunrise + 620 ) + ((intervalFadeMin * 2) + 2);       //+10:32 hores        Llum de lluma 2
    int hora11 = (crvSunrise + 620 ) + ((intervalFadeMin * 3) + 3);       //+10:48 hores        Llum de lluna 3
    int hora12 = crvSunrise + 900;                                        //+15 hores           Fosc
    int hora13 = (crvSunrise + 900 ) + (intervalFadeMin + 1);
    */
    /***************************Encendido de Leds para horari de otoño***************************/

    int hora1 = crvSunrise - ((intervalFadeMin * 3) + 3);                 //-48 min             Inici Llum Lluna
    int hora2 = crvSunrise - ((intervalFadeMin * 2) + 2);                 //-32 min             Inici Albada vermella
    int hora3 = crvSunrise - (intervalFadeMin + 1);                       //-16 min             Sortida del Sol 1
    int hora4 = crvSunrise;                                               //                    Sortida del Sol 2
    int hora5 = crvSunrise + (intervalFadeMin + 1);                       //+16 min             Sortida del Sol 3
    int hora6 = crvSunrise + 180;                                         //+4 hores            Sol a zenit
    int hora7 = crvSunrise + 540;                                         //+9 hores            Sol down
    int hora8 = crvSunrise + 620;                                         //+10 hores           Inici Posta de sol
    int hora9 = (crvSunrise + 620 ) + (intervalFadeMin + 1);              //+10:16 hores        Llum de lluma 1
    int hora10 = (crvSunrise + 620 ) + ((intervalFadeMin * 2) + 2);       //+10:32 hores        Llum de lluma 2
    int hora11 = (crvSunrise + 620 ) + ((intervalFadeMin * 3) + 3);       //+10:48 hores        Llum de lluna 3
    int hora12 = crvSunrise + 900;                                        //+15 hores           Fosc
    int hora13 = (crvSunrise + 900 ) + (intervalFadeMin + 1);

    /*************************** Encendido de Leds para horario de hinvierno***************************
    int hora1 = crvSunrise - ((intervalFadeMin * 3) + 3);                 //-48 min             Inici Llum Lluna
    int hora2 = crvSunrise - ((intervalFadeMin * 2) + 2);                 //-32 min             Inici Albada vermella
    int hora3 = crvSunrise - (intervalFadeMin + 1);                       //-16 min             Sortida del Sol 1
    int hora4 = crvSunrise;                                               //                    Sortida del Sol 2
    int hora5 = crvSunrise + (intervalFadeMin + 1);                       //+16 min             Sortida del Sol 3
    int hora6 = crvSunrise + 180;                                         //+3 hores            Sol a zenit
    int hora7 = crvSunrise + 480;                                         //+8 hores            Sol down
    int hora8 = crvSunrise + 540;                                         //+9 hores            Inici Posta de sol
    int hora9 = (crvSunrise + 540 ) + (intervalFadeMin + 1);              //+9:16 hores         Llum de lluma 1
    int hora10 = (crvSunrise + 540 ) + ((intervalFadeMin * 2) + 2);       //+9:32 hores         Llum de lluma 2
    int hora11 = (crvSunrise + 540 ) + ((intervalFadeMin * 3) + 3);       //+9:48 hores         Llum de lluna 3
    int hora12 = crvSunrise + 780;                                        //+13 hores           Fosc
    int hora13 = (crvSunrise + 780 ) + (intervalFadeMin + 1);
  */

  /**************** Medición de Temperatura i encendido de Calentador o ventiladores*****************/
  sensors1.requestTemperatures();                                         //Se envía el comando para leer la temperatura
  float temp1 = sensors1.getTempC(address1);                              //Se obtiene la temperatura en ºC
  if (ventiladoresEstado == false && (temp1 > tempVentOn)) {              //VENTILADOR - CALENTADOR Si temp >26 refrijera hasta 25 - Si Temp <23.5 calienta hasta 24.5
    ventiladoresEstado = true;
    digitalWrite(ventiladoresPin, HIGH);
  }
  else if (ventiladoresEstado == true && (temp1 < tempVentOff)) {
    ventiladoresEstado = false;
    digitalWrite(ventiladoresPin, LOW);
  }
  if (calentadorEstado == false && (temp1 < tempCalentOn)) {
    calentadorEstado = true;
    digitalWrite(calentadorPin, HIGH);
  }
  else if (calentadorEstado == true && (temp1 > tempCalentOff)) {
    calentadorEstado = false;
    digitalWrite(calentadorPin, LOW);
  }

  /***************************Encendido y apagado de oxigenacion***************************/
  if (oxigenacionEstado == false && ((tempsAraMin >= hora1) && (tempsAraMin < hora12))) {
    oxigenacionEstado = true;
    digitalWrite(oxigenacionPin, HIGH);
  }
  else if (oxigenacionEstado == true && ((tempsAraMin < hora1)  || (tempsAraMin > hora12))) {
    oxigenacionEstado = false;
    digitalWrite(oxigenacionPin, LOW);
  }


  /*************************** Imprime en pantalla Oled***************************/
  sprintf(diaAraPrint, "%02d/%02d/%02d", now.day(), now.month(), now.year());
  sprintf(horaAraPrint, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
  sprintf(hora1Print, "%02d:%02d", (hora1 / 60), (hora1 - ((hora1 / 60) * 60)));
  sprintf(hora3Print, "%02d:%02d", (hora2 / 60), (hora2 - ((hora2 / 60) * 60)));
  sprintf(hora8Print, "%02d:%02d", (hora8 / 60), (hora8 - ((hora8 / 60) * 60)));
  sprintf(hora12Print, "%02d:%02d", (hora12 / 60), (hora12 - ((hora12 / 60) * 60)));

  millisAraPrint = millis();
  while (var1 <= 1) {
    millisAbansPrint = millis();
    var1++;
  }

  if (millisAraPrint - millisAbansPrint < 4000) {

    u8g2.firstPage();
    do {
      u8g2.clearBuffer();
      u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.setCursor(0, 15);
      u8g2.print(diaAraPrint);
      u8g2.setCursor(0, 35);
      u8g2.print(horaAraPrint);
      u8g2.setCursor(0, 60);
      u8g2.print(F("Temp: "));
      u8g2.print(temp1);
    } while ( u8g2.nextPage() );
  }

  else if ((millisAraPrint - millisAbansPrint > 4000) && (millisAraPrint - millisAbansPrint < 8000)) {

    u8g2.firstPage();
    do {
      u8g2.clearBuffer();
      u8g2.setFont(u8g2_font_ncenB12_tr);
      u8g2.setCursor(0, 15);
      u8g2.print(F("Ll:  "));
      u8g2.print(hora1Print);
      u8g2.print("  ");
      u8g2.print(intensitatVermAlbada);
      u8g2.setCursor(0, 30);
      u8g2.print(F("Al:  "));
      u8g2.print(hora3Print);
      u8g2.print("  ");
      u8g2.print(intensitatBlanc);
      u8g2.setCursor(0, 45);
      u8g2.print(F("Ps:  "));
      u8g2.print(hora8Print);
      u8g2.print("  ");
      u8g2.print(intensitatVermOcaso);
      u8g2.setCursor(0, 60);
      u8g2.print(F("Fs:  "));
      u8g2.print(hora12Print);
      u8g2.print("  ");
      u8g2.print(intensitatBlau);
    } while ( u8g2.nextPage() );
  }
  else if (millisAraPrint - millisAbansPrint > 8000) {
    var1 = 0;
  }

  /*************************** Encendido i apagado de Luces segun hora***************************/
  if ((tempsAraMin >= hora1) && (tempsAraMin <= hora2)) {
    if (cambio == true) {
      amanecerAzul();
    }
  }
  else if ((tempsAraMin >= hora2) && (tempsAraMin <= hora3)) {
    if (cambio == false) {
      amanecerRojo();
    }
  }
  else if ((tempsAraMin >= hora3) && (tempsAraMin <= hora4)) {
    if (cambio == true) {
      amanecerBlanco1();
    }
  }
  else if ((tempsAraMin >= hora4) && (tempsAraMin <= hora5)) {
    if (cambio == false) {
      amanecerBlanco2();
    }
  }
  else if ((tempsAraMin >= hora5) && (tempsAraMin <= hora6)) {
    if (cambio == true) {
      amanecerBlanco3();
    }
  }
  else if ((tempsAraMin >= hora6) && (tempsAraMin <= hora7)) {
    if (cambio == false) {
      solZenitUp();
    }
  }
  else if ((tempsAraMin >= hora7) && (tempsAraMin <= hora8)) {
    if (cambio == true) {
      solZenitDown();
    }
  }
  else if ((tempsAraMin >= hora8) && (tempsAraMin <= hora9)) {
    if (cambio == false) {
      ocasoRojo();
    }
  }
  else if ((tempsAraMin >= hora9) && (tempsAraMin <= hora10)) {
    if (cambio == true) {
      ocasoAzul1();
    }
  }
  else if ((tempsAraMin >= hora10) && (tempsAraMin <= hora11)) {
    if (cambio == false) {
      ocasoAzul2();
    }
  }
  else if ((tempsAraMin >= hora11) && (tempsAraMin <= hora12)) {
    if (cambio == true) {
      ocasoAzul3();
    }
  }
  else if ((tempsAraMin >= hora12) && (tempsAraMin <= hora13)) {
    if (cambio == false) {
      lunaZenitDown();
    }
  }
}

/********************************* AMANECER AZUL LEDS SK6812 RGBW*********************************
   Se encienden los leds uno a uno con incremento de intensidad.
   El brillo es proporcional a la fase de la luna real en la posicion establecida:
   Luna nueva intensidad 0 hasta Luna llena intensidad 255
*/
void amanecerAzul() {
  while (var <= 2) {
    intensitatVermAlbada = random(25, 255);
    intensitatVermOcaso = random(25, 255);
    intensitatBlanc = random(100, 255);
    var++;
  }
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / pixelsTots)) {
    millisAbans = millisAra;
    if (i < NUMPIXELS) {
      i++;
    }
    else {
      i = -1;
      cambio = false;
      var = 0;
    }
    for (int j = 0; j < intensitatBlau; j++) {
      tira.setPixelColor(i, tira.Color(0, 0, j, 0));
      tira.show();
    }
  }
}


/*********************************** AMANECER ROJO LEDS SK6812 RGBW***********************************
   Se encienden los leds uno si uno no con incremento de intensidad.
   El brillo cambia cada dia y es aleatorio entre 25 y 255 para simular amaneceres mas o menos rojizos
*/
void amanecerRojo() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsMeitat))) {
    millisAbans = millisAra;
    if (i < NUMPIXELS) {
      i = i + 2;
    }
    else {
      i = -1;
      cambio = true;
    }
    for (int j = 0; j < intensitatVermAlbada; j++) {
      tira.setPixelColor(i, tira.Color(j, 0, 0, 0));
      tira.show();
    }
  }
}
/* **********************************AMANECER BLANCO LEDS SK6812 RGBW***********************************
   Se encienden los leds uno de cada 3 con incremento de intensidad.
   Hay 3 fases de encendido. La primera fase enciende a partir del Led 0, la segunda del Led 1 y la tercera del Led 2
   Finaliza con todos los Leds encendidos en intensidad 100
*/
void amanecerBlanco1() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTer))) {
    millisAbans = millisAra;
    if (i2 < NUMPIXELS) {
      i2 = i2 + 3;
    }
    else {
      i2 = -3;
      cambio = false;
    }
    for (int j = 0; j < 100; j++) {
      tira.setPixelColor(i2, tira.Color(0, 0, 0, j));
      tira.show();
    }
  }
}
void amanecerBlanco2() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTer))) {
    millisAbans = millisAra;
    if (i1 < NUMPIXELS) {
      i1 = i1 + 3;
    }
    else {
      i1 = -2;
      cambio = true;
    }
    for (int j = 0; j < 100; j++) {
      tira.setPixelColor(i1, tira.Color(0, 0, 0, j));
      tira.show();
    }
  }
}
void amanecerBlanco3() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTer))) {
    millisAbans = millisAra;
    if (i < NUMPIXELS) {
      i = i + 3;
    }
    else {
      i = -1;
      cambio = false;
    }
    for (int j = 0; j < 100; j++) {
      tira.setPixelColor(i, tira.Color(0, 0, 0, j));
      tira.show();
    }
  }
}
/*********************************** LUZ DE SOL DIA BLANCO LEDS SK6812 RGBW****************************
   Se encienden los leds uno a uno con incremento de intensidad.
   El brillo cambia cada dia y es aleatorio entre 100 y 255 para simular dias de nubes o de pleno sol
*/
void solZenitUp() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTots))) {
    millisAbans = millisAra;
    if (i < NUMPIXELS) {
      i++;
    }
    else {
      i = -1;
      cambio = true;
    }
    for (int j = 100; j < intensitatBlanc; j++) {
      tira.setPixelColor(i, tira.Color(0, 0, 0, j));
      tira.show();
    }
  }
}
/************************************LUZ DE SOL TARDE BLANCO LEDS SK6812 RGBW**********************
   Disminuye la intensidad de los leds uno a uno hasta 100 para simular la tarde
*/
void solZenitDown() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTots))) {
    millisAbans = millisAra;
    if (i < NUMPIXELS) {
      i++;
    }
    else {
      i = -1;
      cambio = false;
    }
    for (int j = intensitatBlanc; j >= 100; j--) {
      tira.setPixelColor(i, tira.Color(0, 0, 0, j));
      tira.show();
    }
  }
}
/*********************************** OCASO ROJO LEDS SK6812 RGBW***********************************
   Se encienden los leds uno si uno no con incremento de intensidad.
   El brillo cambia cada dia y es aleatorio entre 25 y 255 para simular ocasos mas o menos rojizos
*/
void ocasoRojo() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsMeitat))) {
    millisAbans = millisAra;
    if (i < NUMPIXELS) {
      i = i + 2;
    }
    else {
      i = -1;
      cambio = true;
    }
    for (int j = 0; j < intensitatVermOcaso; j++) {
      tira.setPixelColor(i, tira.Color(j, 0, 0, 0));
      tira.show();
    }
  }
}
/************************************ OCASO AZUL LEDS SK6812 RGBW***********************************
   Se encienden los leds uno de cada 3 con incremento de intensidad.
   Hay 3 fases de encendido. La primera fase enciende a partir del Led 0, la segunda del Led 1 y la tercera del Led 2
   Finaliza con todos los Leds encendidos en intensidad de luz proporcional a la fase de la Luna
*/
void ocasoAzul1() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTer))) {
    millisAbans = millisAra;
    if (i2 < NUMPIXELS) {
      i2 = i2 + 3;
    }
    else {
      i2 = -3;
      cambio = false;
    }
    for (int j = 0; j < intensitatBlau; j++) {
      tira.setPixelColor(i2, tira.Color(0, 0, j, 0));
      tira.show();
    }
  }
}
void ocasoAzul2() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTer))) {
    millisAbans = millisAra;
    if (i < NUMPIXELS) {
      i = i + 3;
    }
    else {
      i = -1;
      cambio = true;
    }
    for (int j = 0; j < intensitatBlau; j++) {
      tira.setPixelColor(i, tira.Color(0, 0, j, 0));
      tira.show();
    }
  }
}
void ocasoAzul3() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTer))) {
    millisAbans = millisAra;
    if (i1 < NUMPIXELS) {
      i1 = i1 + 3;
    }
    else {
      i1 = -2;
      cambio = false;
    }
    for (int j = 0; j < intensitatBlau; j++) {
      tira.setPixelColor(i1, tira.Color(0, 0, j, 0));
      tira.show();
    }
  }
}
/********************************* APAGADO LUZ DE LUNA AZUL LEDS SK6812 RGBW*********************************
   Se apagan los leds uno a uno con intensidad decreciente
*/
void lunaZenitDown() {
  millisAra = millis();
  if ((millisAra - millisAbans) >= (intervalFade / (pixelsTots))) {
    millisAbans = millisAra;
    if (i < NUMPIXELS) {
      i++;
    }
    else {
      i = -1;
      cambio = true;
    }
    for (int j = intensitatBlau; j >= 0; j--) {
      tira.setPixelColor(i, tira.Color(0, 0, j, 0));
      tira.show();
      tira.clear();
    }
  }
}

Las librerías por favor indica de donde las obtienes, si se trata del Adminstrador de Librerías simplemente lo indicas de lo contrario pon el sitio de donde la has descargado.

Lo que veo es una máquina de estados conformada por tus if () que terminan activando secuncias de colores adecuados de acuerdo al momento del dia simulando la luz solar.
Por otro lado, tmb haría lo mismo con la visualización en el LCD y la lectura de sensores.
Ahora en que mejoro tu funcionamiento? En nada, solo es una forma diferente de hacerlo.
Tu código esta muy bien.

Ahora que miro mejor encuentro algo que si es una mejora significativa.
Por tus comentarios en el código hay secuencias para diferentes momentos del año que no tienes almacenados, lo que me hace pensar que debes recompilarlo durante las estaciones.
Que tal si optimizamos esa parte?

Muchas gracias @Surbyte. Tus palabras son muy reconfortantes para un novato como yo.
Tal como sugieres he modificado el post original poniendo el código a vista y he indicado de donde provienen las librerías.
También he investigado un poco en las mejoras que me propones y he visto que respecto a la automatización del cambio horario hay 2 posibilidades:

Mi preferencia seria la segunda porque me permite aprender algo más de programación, pero me encuentro con mi sketch ya ocupa el 91% de almacenamiento del programa y no tengo claro que pueda poner mucho más código. De hecho ya tuve que suprimir información que quería visualizar en la pantalla porque sobrepasaba el límite de los 32256 bytes, y esto me lleva a algunas preguntas:

Puedo reducir el tamaño del sketch o solo tengo la opción de pasarme a un Arduino Mega?
Durante este año, mientras hacía pruebas con el código, me pareció que toda la parte del código referente a mostrar algo en monitor serie o en pantallas se come bytes que da gusto. ¿Esto es una percepción mía o es así? ¿Se puede programar de otra forma que sea más económica?

Muchas gracias.

Nota importante
Quiero agradecerte porque pocas veces encuentro a alguien que postee informando como corresponde todo lo que usa.
Eso facilita las cosas no solo de quienes te respondamos sino de cualquiera que desee repetir tu proyecto.

Comienzo con mis sugerencias:
He mirado tu código y el responsable número 1 del consumo de flash es el display y peor aun la carga especial de la fuente.

u8g2.setFont(u8g2_font_ncenB10_tr);                     // Establece formato de letra

Si eliminas eso y usas la fuente por defecto baja considerablemente el uso de la flash.
Entonces aqui un Mega no es una mala opción si es que tienes pensando agregar mas cosas.

He mejorado en algo tu código bajándolo a 79% pero con una trampa.
Tmb bajé el consumo de RAM y esta mejora si puede continuar.
La trampa es que desactivo el cambio de fuente y dejo la que este por defecto.

int condicion = (millisAraPrint - millisAbansPrint) / 4000;
  switch(condicion) {
    case 0: u8g2.firstPage();
            do {
              u8g2.clearBuffer();
              //u8g2.setFont(u8g2_font_ncenB14_tr);
              u8g2.setCursor(0, 15);
              sprintf(buffer, "%02d/%02d/%02d", now.day(), now.month(), now.year());
              u8g2.print(buffer);
              u8g2.setCursor(0, 35);
              sprintf(buffer, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
              u8g2.print(buffer);
              u8g2.setCursor(0, 60);
              u8g2.print(F("Temp: "));
              u8g2.print(temp1);
            } while ( u8g2.nextPage() );
            break;
    case 1: u8g2.firstPage();
            do {
              u8g2.clearBuffer();
              //u8g2.setFont(u8g2_font_ncenB12_tr);
              u8g2.setCursor(0, 15);
              u8g2.print(F("Ll:  "));
              sprintf(buffer, "%02d:%02d", (hora1 / 60), (hora1 - ((hora1 / 60) * 60)));
              u8g2.print(buffer);
              u8g2.print("  ");
              u8g2.print(intensitatVermAlbada);
              u8g2.setCursor(0, 30);
              u8g2.print(F("Al:  "));
              sprintf(buffer, "%02d:%02d", (hora2 / 60), (hora2 - ((hora2 / 60) * 60)));
              u8g2.print(buffer);
              u8g2.print("  ");
              u8g2.print(intensitatBlanc);
              u8g2.setCursor(0, 45);
              u8g2.print(F("Ps:  "));
              sprintf(buffer, "%02d:%02d", (hora8 / 60), (hora8 - ((hora8 / 60) * 60)));
              u8g2.print(buffer);
              u8g2.print("  ");
              u8g2.print(intensitatVermOcaso);
              u8g2.setCursor(0, 60);
              u8g2.print(F("Fs:  "));
              sprintf(buffer, "%02d:%02d", (hora12 / 60), (hora12 - ((hora12 / 60) * 60)));
              u8g2.print(buffer);
              u8g2.print("  ");
              u8g2.print(intensitatBlau);
            } while ( u8g2.nextPage() );
            break;
    case 2: var1 = 0;
            break;
  }

Ahh si elimné tus if y armé un switch case con las 3 condiciones

if (millisAraPrint - millisAbansPrint < 4000) {
else if ((millisAraPrint - millisAbansPrint > 4000) && (millisAraPrint - millisAbansPrint < 8000)) {
 else if (millisAraPrint - millisAbansPrint > 8000) {

Estas lineas desaparecen y agregas solo una

char buffer[16];

El archivo u8g2_fonts que esta en
C:\Users[USUARIO]\Documents\Arduino\libraries\U8g2\src\clib
tiene un tamaño de 29K
Acá dice como optimizar esto

Aún no me funcionó como esperaba.
La idea será reducir dicho archivo pero no se puede hacer sin criterio.

Hola @Gertru, me interesa mucho tu proyecto y sobre todo el tema de la iluminación a ver qué resultados te da. ¿Cuántos leds has puesto para tus 60 l? Lo tienes plantado y sabes los lumens que aportan esa tira??

He leído en los comentarios que el brillo de los leds por la noche es proporcional a la fase de la luna real, estudiaré tu algoritmo también me parece superinteresante. ¡Enhorabuena por tu trabajo!

Yo también estoy inmerso en un proyecto parecido, aunque me he complicado un poco y voy muy lento. Mi acuario es de 220 litros y no quería una gran pantalla con ventiladores y he optado por SMD5050, tengo plaquitas de 9 led para rojos y azules y otras de 36 leds para el blanco en total algo mas 600 led. Esa parte aún no la he montado y el montaje eléctrico va a ser interesante. Usando esas tiras se simplificaría mucho y las opciones de configuración infinitas. Aunque no sé el resultado para el acuario y las plantas, de ahí que conocer tu experiencia me vendría muy bien.

En la parte de controladores es donde he sido un poco ambicioso de partida y voy mas lento, aunque ya está acabada, finalizando las pruebas y en breve pasaré a la pantalla del acuario.
Utilizo:

  • NodeMCU para parametrizar, lanzar eventos, IOT ya que se puede controlar y ver info a través de Blynk.

  • ATMega2560 para controlar:
    Tft de 28’’
    Sonda DS18B20
    Tres vías de iluminación Blanca, Roja y Azul
    Comedero
    Sensor DHT22
    Oxigenador
    Calentador
    Filtro

La comunicación entre ambos por I2C.

Reitero mi enhorabuena por tu trabajo, y si pudieras aportar datos de la pantalla del acuario seguro sería muy interesante. Y por supuesto cualquier ayuda que pueda aportar sería un placer, aunque me quito el sombrero ante los moderadores y usuarios más activos, por compartir su experiencia con el resto.

Un saludo.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.