Go Down

Topic: Reloj simulador ciclo solar (Read 1 time) previous topic - next topic

ea7ln

Tras concluir el diseño del control de temperatura de mis acuarios, quiero seguir ampliando funciones.
Ahora quiero controlar el encendido y apagado de las luces, manteniendo de una forma aproximada, (no es necesario una exactitud extrema), el ciclo solar.
La idea es que las luces enciendan y apaguen de forma dimerizada en base a la hora del día que sea.
Tengo que controlar 3 canales PWM, uno para leds blancos, otro para leds azul y otro para leds rojos.
Al amanecer prevalecerá la luz roja y se irá mezclando la luz blanca conforme avance el dia, hasta el maximo valor que será el cenit del sol a la hora de medio dia.
Al atardecer vovlerá a mezclar la luz roja y al anochecer, la luz azul durante toda la noche para simular la luz de la luna, y volverá a comenzar el ciclo.
Os explico esto porque me gustaria que me aconsejarais, teniendo en cuenta que mi nivel en programación es amateur.
He encontrado proyectos similares por la red, pero son muy complicados y no entiendo el código.
En primer lugar quería saber como puedo sumar valores horarios.
Tengo que hacer cálculos para que desde el equinocio de verano el día 21 de junio, hasta el equinocio de invierno el día 21 de diciembre, vaya adelantando la hora del amanecer aproximadamente 1 minuto al día, y al contrario desde el equinocio de invierno, hasta el de verano.
Además tengo que variar la luminosidad de los tres canales PWM conforme avance el día.
De momento he estado haciendo pruebas y aprendiendo a usar el modulo RTC para poder controlar el tiempo con un DS3231, pero no se como plantear el calculo de esas variaciones.
Os dejo el código que quería usar como base.
Agradecería vuestros consejos y/o ejemplos.



Code: [Select]

//Reloj con RTC DS3231 y display I2C

#include <Wire.h>
#include "DS3231.h"
RTClib RTC;
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
//#define I2C_ADDR    0x27

LiquidCrystal_I2C lcd( 0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE ); //0x27 direccion I2C display, resto pines de funcinamiento del display(no variarlo) no tiene que ver con arduino, POSITIVE back light

const int out_blanco=3;  //Nombra out_blanco para pin 3
int ciclo=0;
int h_on; //Hora de alarma
int m_on; // Minuto de alarma
int s_on; //Segundos de alarma
int flag_alarma; // Bandera alarma activada/desativada. 0=desactivada. 1=activada



void setup()
   {

    flag_alarma=0;
    analogWrite(out_blanco,LOW); 
    pinMode (out_blanco, OUTPUT);  // configura out_blanco "pin3" como salida
    Serial.begin(9600);
    Wire.begin();
    lcd.begin (16,2);    // Inicializar el display con 16 caraceres 2 lineas
   }
void loop()
   {
    lcd.clear(); 
    lcd.home ();
    DateTime now = RTC.now();
    lcd.print(now.year(), DEC);
    lcd.print('/');
    if (now.month()<=9) lcd.print('0'); // Si es valor < a 9 pongo un cero para que los caracteres sean siemopre de dos digitos 00:00:00
    lcd.print(now.month(), DEC);
    lcd.print('/');
    if (now.day()<=9) lcd.print('0');
    lcd.print(now.day(), DEC);
   
    lcd.setCursor ( 0, 1 );
    if (now.hour()<=9) lcd.print('0');
    lcd.print(now.hour(), DEC);
    lcd.print(':');
    if (now.minute()<=9) lcd.print('0');
    lcd.print(now.minute(), DEC);
    lcd.print(':');
    if (now.second()<=9) lcd.print('0');
    lcd.print(now.second(), DEC);

    h_on=21;   //---
    m_on=0; //   |--Tiempo de alarma de encendido.
    s_on=0; //---
   
    if((now.hour()==h_on)&&(now.minute()==m_on)&&(now.second()==s_on)) //Si el tiempo coincide con la hora fijada salta alarma
      {
         ciclo=75;
         analogWrite (out_blanco,ciclo);
         flag_alarma=1;
      }

    if((now.hour()==h_on)&&(now.minute()==m_on)&&(now.second()==s_on+10))
      {
       ciclo=ciclo+75;
         analogWrite (out_blanco,ciclo);
      }

    if((now.hour()==h_on)&&(now.minute()==m_on)&&(now.second()==s_on+20))
      {
       ciclo=255;
         analogWrite (out_blanco,ciclo);
      }
    delay(1000);
    }

Kike_GL

#1
Jun 01, 2018, 02:10 am Last Edit: Jun 01, 2018, 02:42 am by Kike_GL
el ciclo solar.
Define ciclo solar: Es un lapso de 11 años durante el cual varían la cantidad de manchas, ráfagas y protuberancias solares. Segun Google.

Pretendes que el RTC dure eso ?

La mejor forma de hacer calculos con fechas es usando el tiempo Unix que es el numero se segundos transcurridos desde el 1-ENE-1970 0:0:0

Ese numero lo obtienes con el metodo now.unixtime() y por ejemplo si le quieres sumar 1 hora seria  now.unixtime() + 3600.

Porque no usas mejor la libreria RTClib.h, la libreria DS3231.h es muy vieja.
Saludos, Kike_GL

ea7ln

Gracias por tu respuesta Kike.
Es evidente que no he sabido explicarme. Cuando digo ciclo solar, quiero referirme al ciclo diario del sol.
Amanecer, cenit y puesta de sol.
Cada día el ciclo se repite, pero con una pequeña diferencia horaria, aprox 1 min mas de sol cada día, si avanzamos hacia verano, y al contrario si vamos de verano a invierno.
El motivo de no usar la librería RTClib.h, es porque no conseguía sincronizar la hora del RTC con la de Windows. Ademas estuve buscando en internet, los comandos de esa libreria para saber cuales utilizar, y no conseguí encontrar información.

Saludos

Kike_GL

#3
Jun 01, 2018, 05:54 pm Last Edit: Jun 01, 2018, 06:21 pm by Kike_GL
Cada día el ciclo se repite, pero con una pequeña diferencia horaria, aprox 1 min mas de sol cada día, si avanzamos hacia verano, y al contrario si vamos de verano a invierno.
Si lo quisieres es calcular la hora de los crepúsculos (mañana y tarde), la hora de salida, pico y puesta de sol y la luna, esos son cálculos matemáticos complejos que varian por la ubicación terrestre (ciudad donde estas) y la fecha actual. Dale una mirada a calendario-lunar.net.

Antes de lanzarte con esos cálculos complejos yo te recomendaría iniciar tu programación con valores fijos (que los podrías obtener de la pagina que te di). Mira el cuadro "Ingrese los datos manualmente"

Una idea que podrías aplicar posteriormente en tu proyecto es usa un sensor fotoeléctrico que te daria la verdadera iluminación real y evitarías todos esos cálculos complejos.

El motivo de no usar la librería RTClib.h, es porque no conseguía sincronizar la hora del RTC con la de Windows. Ademas estuve buscando en internet, los comandos de esa libreria para saber cuales utilizar, y no conseguí encontrar información.
Justamente la librería que te recomiendo es de Adafruit por lo que esta extensamente documentada.

Inicia con:
Code: [Select]

#include <Wire.h>
#include <RTClib.h>
RTC_DS3231 rtc;


Luego de creado el objeto RTC (con ultima linea) puedes usar los métodos:
Code: [Select]

rtc.begin()
rtc.isrunning()
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));  //Poner fecha y hora de compilación
rtc.adjust(DateTime(2018, 6, 1, 10, 42, 22));   //Año, mes, dia, hora, minuto, segundo
rtc.initialized()
rtc.lostPower()
rtc.now()  //Instancias variable tipo DateTime


Luego de instanciada la varible, por ejemplo DateTime hoy.RTC.now(); puedes usar los métodos:
Code: [Select]

hoy = rtc.now();
hoy.year()
hoy.month()
hoy.day()
hoy.hour()
hoy.minute()
hoy.second()
hoy.unixtime()



Avanza un poco con eso y publicas tu código.
Saludos, Kike_GL

surbyte

Lo que si se puede hacer @KIGE_GL es un parser (algo que lea la pagina) y tome los datos que hacen falta.

Encontré uno mejor que calcula para tu ciudad o cualquier ciudad del mundo
Sunrise, Sunset, and Daylength

Obvio que el enlace apunta a mi ciudad para pueden facilmente elegir la suya.
Con algo asi podria armar un parser como dije antes que lea los datos de la página y controlen de ese modo las acciones del arduino.


noter

Recuerdo que en una ocasión tratamos algo similar.

Aquí está.

Kike_GL

Lo que si se puede hacer @KIGE_GL es un parser (algo que lea la pagina) y tome los datos que hacen falta.
Si es cierto, de poder se puede poniendo primero un modulo WiFi. Yo me plantearía esa opción en la siguiente versión, pero primero me enfocaría en lograr lo que quiere con horas fijas. Es mucho mejor obtener pequeños logros rápidamente y no paralizarse complicando mas el proyecto.
Saludos, Kike_GL

surbyte

Pensé que queria desplazar la hora del sol 1 minuto por dia, dime con el RTC como lo hará?
Solo le agregas 1 min de modo arbitrario?
El resultado final que tan cercano a la realidad será?

Quote
He encontrado proyectos similares por la red, pero son muy complicados y no entiendo el código.
Cuales son esos proyectos?

ea7ln

#8
Jun 10, 2018, 09:49 pm Last Edit: Jun 12, 2018, 02:09 pm by ea7ln
Pensé que queria desplazar la hora del sol 1 minuto por dia, dime con el RTC como lo hará?
Solo le agregas 1 min de modo arbitrario?
El resultado final que tan cercano a la realidad será?

Cuales son esos proyectos?
El proyecto mas completo que he encontrado ha sido este


http://acubiomed.com/cao/



El cual para mi es complicado de entender. Comprendo que para ti, o para cualquier programador sea facil de entender y de dar una solución a cualquier problema, porque conoceis este mundo y pensáis como el microprocesador.
Yo estudié electrónica en 1985, imagínate nada de microprocesadores, y poco a poco voy haciendo cosas con ellos, pero a veces como pienso en analógico, una solución facil, me cuensta trabajo encontrarla.
Estoy muy liado de trabajo, cuando tenga algo que enseñaros, os lo mostraré para que me aconsejeis.

Gracias a todos por vuestras aportaciones.

car127

#9
Jun 11, 2018, 07:17 pm Last Edit: Jun 12, 2018, 06:06 pm by car127
viste aca arta info solo buscar  para comensar

https://todomarino.com/forum/foros/taller-de-arduino.162/

surbyte

@ea7ln y @car127 en este foro usamos etiquetas, no posteamos enlaces asi

https://todomarino.com/forum/foros/taller-de-arduino.162/
Editen por favor!

ArduMyth

Si tan importante es que la hora sea exacta en vez de usar un RTC mejor un ESP8266 o un shield ethernet y coger el dato desde un NTP server, por ejemplo usando: pool.ntp.org

ea7ln

Poco a poco voy avanzado el proyecto. Voy creando código y necesito probar de una manera rápida, por eso intento variar la hora del RTC, para no tener que esperar a que llegue por ejemplo las 7:00 para ver si se enciende un led o no.
El código es hasta el momento este

Code: [Select]

[code]
//Date 12/06/2018
//Reloj con RTC DS3231 y display I2C

#include <Wire.h>
#include "DS3231.h"
RTClib RTC;
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
//#define I2C_ADDR    0x27

LiquidCrystal_I2C lcd( 0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE ); //0x27 direccion I2C display, resto pines de funcinamiento del display(no variarlo) no tiene que ver con arduino, POSITIVE back light

const int out_blanco=3;  //Nombra out_blanco para pin 3
const int out_azul=4;
const int out_rojo=5;
int ciclo_blanco=0; // ciclo de trabajo WFM salida led
int ciclo_azul=0;
int ciclo_rojo=0;

byte amanecer=0;
byte zenit=0;
byte atardecer=0;
byte ocaso=0;

int a=0;

void amanece() //Subprograma de simulacion de amanecer
  {

   ciclo_rojo=100/a;
   analogWrite (out_rojo,ciclo_rojo);
   ciclo_blanco=((100/a)/4);
   analogWrite (out_blanco,ciclo_blanco);
  }
void mediodia()
  {
    //cliclo_rojo viene de amanece en 100% y lo mantengo
    if (ciclo_blanco>=100) ciclo_blanco=100;
    ciclo_blanco=((100/a)*2);
    analogWrite (out_blanco,ciclo_blanco);
    ciclo_azul=ciclo_blanco;
    analogWrite (out_azul,ciclo_blanco);
  }
void atardece()
{
 
}
void puestasol()
{
 
}




void setup()
   {

   
    analogWrite(out_blanco,LOW); 
    pinMode (out_blanco, OUTPUT);  // configura out_blanco "pin3" como salida
    analogWrite(out_azul,LOW); 
    pinMode (out_azul, OUTPUT);  // configura out_azul "pin4" como salida
    analogWrite(out_rojo,LOW); 
    pinMode (out_rojo, OUTPUT);  // configura out_rojo "pin5" como salida
   
    Serial.begin(9600);
    Wire.begin();
    lcd.begin (16,2);    // Inicializar el display con 16 caraceres 2 lineas
   
   }
   
void loop()
   {
    lcd.clear(); 
    lcd.home ();
 
    DateTime now = RTC.now(); //Inicia el reloj a la fecha y hora del sistema
    lcd.print(now.year(), DEC);
    lcd.print('/');
    if (now.month()<=9) lcd.print('0'); // Si es valor < a 9 pongo un cero para que los caracteres sean siemopre de dos digitos 00:00:00
    lcd.print(now.month(), DEC);
    lcd.print('/');
    if (now.day()<=9) lcd.print('0');
    lcd.print(now.day(), DEC);
   
    lcd.setCursor ( 0, 1 );
    if (now.hour()<=9) lcd.print('0');
    lcd.print(now.hour(), DEC);
    lcd.print(':');
    if (now.minute()<=9) lcd.print('0');
    lcd.print(now.minute(), DEC);
    lcd.print(':');
    if (now.second()<=9) lcd.print('0');
    lcd.print(now.second(), DEC);

   
   
if((now.hour()>=7)&&(now.hour()<=11)) //Si estoy entre las 7 y las 12 horas
  {     
    a=12-now.hour();
    amanece();
  }
 
if((now.hour()>=12)&&(now.hour()<=18)) //Si estoy entre las 12 y las 18 horas
  {
    a=19-now.hour();
    mediodia();

  }

delay(1000);


    }

[/code]

intento cambiar la hora del ordenador porque pensaba que se sincronizaba con el, pero no lo consigo.
También intento con la sentencia

rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
   
escribiendo rtc.adjust(DateTime(2018, 6, 14, 6, 59, 0));

pero si lo coloco en el loop, siempre aparece la misma hora y no cambia, y si lo coloco en el Setup, aparece un mensaje de error

error: 'rtc' was not declared in this scope

rtc.adjust(DateTime(2018, 6, 14, 6, 59, 0));

     
¿Que estoy haciendo mal?
Gracias nuevamente por vuestra ayuda


surbyte

Hay un ejemplo que te permite cambiar la hora usando el puerto serie y la librería Time

Code: [Select]

#include <TimeLib.h>

#define TIME_HEADER  "T"   // Header tag for serial time sync message
#define TIME_REQUEST  7    // ASCII bell character requests a time sync message

void setup()  {
  Serial.begin(9600);
  while (!Serial) ; // Needed for Leonardo only
  pinMode(13, OUTPUT);
  setSyncProvider( requestSync);  //set function to call when sync required
  Serial.println("Waiting for sync message");
}

void loop(){   
  if (Serial.available()) {
    processSyncMessage();
  }
  if (timeStatus()!= timeNotSet) {
    digitalClockDisplay(); 
  }
  if (timeStatus() == timeSet) {
    digitalWrite(13, HIGH); // LED on if synced
  } else {
    digitalWrite(13, LOW);  // LED off if needs refresh
  }
  delay(1000);
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year());
  Serial.println();
}

void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}


void processSyncMessage() {
  unsigned long pctime;
  const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013

  if(Serial.find(TIME_HEADER)) {
     pctime = Serial.parseInt();
     if( pctime >= DEFAULT_TIME) { // check the integer is a valid time (greater than Jan 1 2013)
       setTime(pctime); // Sync Arduino clock to the time received on the serial port
     }
  }
}

time_t requestSync()
{
  Serial.write(TIME_REQUEST); 
  return 0; // the time will be sent later in response to serial mesg
}


La contra es que debes ajustar respecto de esa fecha o modificarlo para ingresar valores mas amigables.

Kike_GL

Code: [Select]

#include <Wire.h>
#include "DS3231.h"

RTClib RTC;


intento cambiar la hora del ordenador porque pensaba que se sincronizaba con el, pero no lo consigo.
También intento con la sentencia

rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
   
escribiendo rtc.adjust(DateTime(2018, 6, 14, 6, 59, 0));

pero si lo coloco en el loop, siempre aparece la misma hora y no cambia, y si lo coloco en el Setup, aparece un mensaje de error

error: 'rtc' was not declared in this scope
Estas instalaciando RTC y tratas de usar el objeto rtc, ese es el error.

El codigo es sensitivo a mayusculas/minuscas.
Saludos, Kike_GL

Go Up