• Skip to primary navigation
  • Skip to main content

ProgramaciónSiemens

Cursos online de automatización industrial con PLC Siemens

  • Cursos
  • Mi cuenta
    • Mi cuenta
    • Blog
    • Foros
    • Curso HMI con Python y Qt-Designer
    • Curso de AWL
    • Curso de iniciación a la Industria 4.0
    • Curso Express de TIA Portal
    • Curso de WinCC Flexible 2008
    • Crear HMI con OPC y VB.NET
    • Crear HMI con Snap7 y VB.NET
    • Curso ViSnap7
    • Curso de TIA Portal para CPU 1200
    • Curso de Step 7 V5.x
    • Curso de comunicaciones IE y Profinet
  • Contacto & Faq

Seguimiento solar con Siemens 1200 TIA Portal

Seguimiento solar con Siemens 1200  TIA Portal

por Iñigo Gútiez · 16 Comments

Recientemente, y debido al proceso de documentación que estoy realizando para el curso de TIA Portal sobre la serie 1200 de Siemens (en el cual veremos ejemplos también en SCL), me he topado con este ejemplo de Seguimiento solar con Siemens 1200 realizado en TIA Portal.

Es un ejemplo publicado en inglés de la empresa Bytex Automation, en Italia. Me he puesto en contacto con ellos para pedirles la oportunidad de traducir el ejemplo a castellano y compartirlo contigo.

Su contacto Massimo me ha dado permiso, por lo que aquí te lo traigo para que lo conozcas si no lo habías visto o bien si la lengua de Shakespeare se te resiste un poco.

La traducción es lo más literal posible para ser fiel a la entrada original.

Contenido

Seguimiento solar con Siemens 1200 y TIA Portal

Este artículo explica como construir un sistema de seguimiento solar con usando un PLC Simatic S7-1200. La función astronómica estças desarrollada en lenguaje SCL. El objetivo principal es desarrollar una función capaz de retornar la elevación del Sol (ángulo de altitud solar), y su ángulo con el norte (ángulo azimutal).

La función retornará también el tiempo que falta para el amanecer y el ocaso, la duración total de horas de sol, el momento en el que se hace de día y cuándo se hace de noche. Puedes usar esta  característica para encender una lámpara en tu jardín cuando el sol se pone o dirigir uno o varios paneles, manejados por ejes motorizados,  siguiendo el sol para conseguir el máximo de energía.

Seguimiento solar con Siemens 1200 Seguimiento solar con Siemens 1200 Seguimiento solar con Siemens 1200

Ejemplos de paneles solares usando uno o dos ejes motorizados

La función necesita algunos parámetros de entrada, como la latitud, longitud y elevación local, la zona horaria, ajuste de luz de día, y finalmente la hora actual dada desde el reloj del PLC.

Función astronómica – Parámetros de entrada

  • LocalLatitude Número decimal representando la latitud local. Asigna números positivos para el hemisferio norte y negativos para el hemisferio sur. Por ejemplo 45.838073
  • LocalLongitude Número decimal que representa la longitud local. Asigna números positivos para meridianos del Este y negativos para el Oeste de Greenwich. Por ejemplo -13.406095)
  • Elevation Número decimal que representa la elevación local sobre el mar medido en metros.
  • TimeZone (Número decimal que representa la zona horaria respecto a Greenwich.
  • DayLightAdjustement Fija DayLightAdjustement = 1  en verano y  DayLightAdjustement = 0 para invierno
  • ActualDateAndTime Fecha y hora actual

Seguimiento solar con Siemens 1200

Función astronómica – Parámetros de salida

  • AltitudeAngle Número decimal que representa el ángulo entre la posición del sol y el horizonte del observador local.
  • AzimuthAngle Número decimal que representa el ángulo entre una dirección de referencia (Norte) y una línea desde el observador hasta la posición del sol proyectada en el mismo plano como la dirección de referencia.
  • SunRiseTime Amanecer en tipo de datos DTL
  • SunSetTime Puesta del Sol en tipo de datos DTL
  • SunDurationTime Duración total de sol en tipo de datos Time
  • IsDay  Booleana que indica el el evento del amanecer
  • IsNight Booleana que indica el evento del anochecer

Cómo funciona: Ajuste de luz solar

Si tu país tiene un sistema de ahorro de luz solar (como por ejemplo España), tienes que ajustar el parámetro DayLightAdjustement=1 en verano, y DayLightAdjustement=0 en invierno. Si no lo tiene, el parámetro tiene que estar siempre a 0.

¿Cómo hacerlo?

Usando la función RD_LOC_T puedes leer la fecha y hora actual del PLC Simatic S7-1200 y leyendo el valor RET_VAL de la función, puedes leer el estado del tiempo de luz solar actual (W#16#0001)

Seguimiento solar con Siemens 1200

 Cómo funciona: Sincronizar el relos del PLC con la hora de internet

¿Cómo hacerlo?

Si tienes una conexión de internet para el PLC es bastante simple. Ve a la configuración del dispositivo en el panel izquierdo del TIA Portal; pica y haz click en el interface PROFINET y selecciona Activar sincronización horaria via servidor NTP y añade una dirección de servidor de hora de internet. Por ejemplo 192.204.114.232.

Seguimiento solar con Siemens 1200

Cómo funciona: Función astronómica de un sistema de seguimiento solar con Siemens 1200

Lenguaje SCL – Esta es la lista de declaración de variables


  // Input parameters
  //-------------------------------
  // LocalLatitude:       Real
  // LocalLongitude:      Real
  // Elevation:           Real
  // TimeZone:            Int
  // DayLightAdjustement: Int
  // ActualDateAndTime:   DTL
  
  // Output parameters
  //-------------------------------
  // AltitudeAngle:       Real
  // AzimuthAngle:        Real
  // SunRiseTime:         DTL
  // SunSetTime:          DTL
  // SunDurationTime:     Time
  // IsDay:               Bool
  // IsNight:             Bool
  // PreSet:              Bool
  
  // Static declarations
  //-------------------------------  
  // #RadiansToDegrees          Real  
  // #DegreesToRadians          Real
  // #Meridian                  Real
  // #HoursAfterMidnight        Real
  // #MinutesAfterMidnight      Real
  // #UT                        Real
  // #CorrectedYear             UInt
  // #CorrectedMonth            USInt
  // #t                         Real
  // #g                         Real
  // #gn                        Real
  // #C                         Real
  // #L                         Real
  // #Alpha                     Real
  // #GHA                       Real
  // #GHAn                      Real
  // #Obliquity                 Real
  // #Declination               Real
  // #EotAdjustment             Real
  // #ClockTimeToLSOTAdjustment Real
  // #SolarHourAngle            Real
  // #ApparentSolarTime         Real
  // #SolarMinutesAfterMidnight Real
  // #whichDay                  Int
  // #HourAngle                 Real
  // #PreAzimuthAngle           Real
  // #x                         Bool
  // #SunRiseSetLSoTMinutes     Real
  // #SunRiseTime_R             Real
  // #SunSetTime_R              Real
  // #SunDurationTime_R         Real
  // #RHour                     Real
  // #RMin                      Real
  // #RSec                      Real
  // #IHOUR                     Int
  // #IMIN                      Int
  // #ISEC                      Int
							

Lenguaje SCL –  Código ejemplo de seguimiento solar


	//******************************************************
	// THIS CODE MUST BE COMPILED AS FUNCTION_BLOCK							
	//******************************************************

    // Define Radians and Degrees conversion
    // -------------------------------------
    #RadiansToDegrees := 57.295779513082323;
    #DegreesToRadians := 0.017453292519943295;
    
    
    #Meridian := -15.0 * INT_TO_REAL(#TimeZone);

    // Calculate Hours after midnight
    // ------------------------------
    #HoursAfterMidnight := INT_TO_REAL(#ActualDateAndTime.HOUR) +
                            INT_TO_REAL(#ActualDateAndTime.MINUTE) / 60.0 +
                            INT_TO_REAL(#ActualDateAndTime.SECOND) / 3600.0;

    // Calculate Minutes after midnight
    // --------------------------------
    #MinutesAfterMidnight := INT_TO_REAL(#ActualDateAndTime.HOUR) * 60.0 +
                            INT_TO_REAL(#ActualDateAndTime.MINUTE) +
                            INT_TO_REAL(#ActualDateAndTime.SECOND) / 60.0;

    // calculate Universal Time
    // ------------------------  
    #UT := #HoursAfterMidnight - INT_TO_REAL(#TimeZone) - INT_TO_REAL(#DayLightAdjustment);
     
    IF #ActualDateAndTime.MONTH > 2 THEN
        #CorrectedYear := #ActualDateAndTime.YEAR;
        #CorrectedMonth := #ActualDateAndTime.MONTH - 3;
    ELSE
        #CorrectedYear := #ActualDateAndTime.YEAR -1;
        #CorrectedMonth := #ActualDateAndTime.MONTH + 9;
    END_IF;

    #t := ((#UT / 24.0) + USINT_TO_REAL(#ActualDateAndTime.DAY) +
          DINT_TO_REAL(FLOOR(30.6 * USINT_TO_REAL(#CorrectedMonth) + 0.5)) + 
          DINT_TO_REAL(FLOOR(365.25 * (UINT_TO_REAL(#CorrectedYear) - 1976.0))) - 8707.5) / 36525.0;
    
    #g := 357.528 + 35999.05 * #t;

    #gn := "NormalizeTo360"(#g);

    #C := (1.915 * SIN(#gn * #DegreesToRadians)) + 
            (0.02 * SIN((2.0 * #gn) * #DegreesToRadians));

    #L := 280.46 + (36000.77 * #t) + #C;

    #Alpha := #L - 2.466 * SIN((2.0 * #L) * #DegreesToRadians) + 
                0.053 * SIN((4.0 * #L) * #DegreesToRadians);

    #GHAn := #UT * 15.0 - 180.0 - #C + #L - #Alpha;
    #GHA := "NormalizeTo360"(#GHAn);

    #Obliquity := 23.4393 - 0.013 * #t;

    #Declination := ATAN(TAN(#Obliquity * #DegreesToRadians) * SIN(#Alpha * #DegreesToRadians));
    #Declination := #Declination * #RadiansToDegrees;

    #EotAdjustment := (#L - #C - #Alpha) / 15.0;   // EOT adjustment in hours

    #ClockTimeToLSOTAdjustment := ((#LocalLongitude - #Meridian) / 15.0) - 
                                    #EotAdjustment + #DayLightAdjustment;

    #SolarHourAngle := 0.0;
    #SolarHourAngle := #GHA - #LocalLongitude;
    #TempReal := "NormalizeTo180"(#SolarHourAngle);
    #SolarHourAngle := #TempReal;
    
    #ApparentSolarTime := 0.0;
    #TempReal := 12.0 + #SolarHourAngle / 15.0;
    #ApparentSolarTime := "NormalizeTo24"(#TempReal);

    #SolarMinutesAfterMidnight := #MinutesAfterMidnight - (#ClockTimeToLSOTAdjustment * 60.0);

    #whichDay := 0;

    #HourAngle := (#SolarMinutesAfterMidnight - 720.0) / 4.0 * -1.0;

    #AltitudeAngle := #RadiansToDegrees * 
                            (ASIN((SIN(#LocalLatitude * #DegreesToRadians) * 
                            SIN(#Declination * #DegreesToRadians)) - 
                            (COS(#LocalLatitude * #DegreesToRadians) * 
                            COS(#Declination * #DegreesToRadians) * 
                            COS((#SolarHourAngle + 180.0) * #DegreesToRadians))));

    #PreAzimuthAngle := #RadiansToDegrees * ACOS((COS(#Declination * #DegreesToRadians) * 
                    ((COS(#LocalLatitude * #DegreesToRadians) * 
                     TAN(#Declination * #DegreesToRadians)) + 
                     (SIN(#LocalLatitude * #DegreesToRadians) * 
                     COS((#SolarHourAngle + 180.0) * #DegreesToRadians)))) / 
                     COS(#AltitudeAngle * #DegreesToRadians));

    #x := False;
    IF (#HourAngle > 0.0) THEN
      IF (#HourAngle < 180.0) THEN
        #x := True;
      END_IF;
    END_IF;

    IF #x THEN
      #AzimuthAngle := (360.0 - #PreAzimuthAngle);
    ELSE
      #AzimuthAngle := #PreAzimuthAngle;
    END_IF;

    #SunRiseSetLSoTMinutes := #RadiansToDegrees * ACOS(-1.0 * 
            (SIN(#LocalLatitude * #DegreesToRadians) * 
            SIN(#Declination * #DegreesToRadians) - 
            SIN((-0.8333 - 0.0347 * SQRT((#Elevation))) * #DegreesToRadians)) / 
            COS(#LocalLatitude * #DegreesToRadians) / 
            COS(#Declination * #DegreesToRadians)) * 4.0;


    #SunRiseTime_R := ((720.0 - #SunRiseSetLSoTMinutes + (#ClockTimeToLSOTAdjustment * 60.0)));
    #TempReal := #SunRiseTime_R;
    #RSec := DINT_TO_REAL(FLOOR((#TempReal - DINT_TO_REAL(FLOOR(#TempReal))) * 60.0));
    #RSec := #RSec + DINT_TO_REAL(FLOOR(#TempReal)) * 60.0;
    #RHour := DINT_TO_REAL(FLOOR(#RSec / 3600.0));
    #RMin := DINT_TO_REAL(FLOOR((#RSec / 3600.0 - #RHour) * 60.0));
    #RSec := #RSec - #RHour * 3600.0 - #RMin * 60.0;
    IF #RSec >= 30.0 AND #RMin < 59 THEN
        #RMin := #RMin + 1.0;
    END_IF;
    #IHOUR := REAL_TO_INT(#RHour);
    #IMIN := REAL_TO_INT(#RMin);
    #ISEC := REAL_TO_INT(#RSec);
    #SunRiseTime := #ActualDateAndTime;
    #SunRiseTime.HOUR := INT_TO_USINT(#IHOUR);
    #SunRiseTime.MINUTE := INT_TO_USINT(#IMIN);
    #SunRiseTime.SECOND := INT_TO_USINT(#ISEC);
    
    
    #SunSetTime_R := ((720.0 + #SunRiseSetLSoTMinutes + (#ClockTimeToLSOTAdjustment * 60.0)));
    #TempReal := #SunSetTime_R;
    #RSec := DINT_TO_REAL(FLOOR((#TempReal - DINT_TO_REAL(FLOOR(#TempReal))) * 60.0));
    #RSec := #RSec + DINT_TO_REAL(FLOOR(#TempReal)) * 60.0;
    #RHour := DINT_TO_REAL(FLOOR(#RSec / 3600.0));
    #RMin := DINT_TO_REAL(FLOOR((#RSec / 3600.0 - #RHour) * 60.0));
    #RSec := #RSec - #RHour * 3600.0 - #RMin * 60.0;
    IF #RSec >= 30.0 AND #RMin < 59 THEN
        #RMin := #RMin + 1.0;
    END_IF;
    #IHOUR := REAL_TO_INT(#RHour);
    #IMIN := REAL_TO_INT(#RMin);
    #ISEC := REAL_TO_INT(#RSec);
    #SunSetTime := #ActualDateAndTime;
    #SunSetTime.HOUR := INT_TO_USINT(#IHOUR);
    #SunSetTime.MINUTE := INT_TO_USINT(#IMIN);
    #SunSetTime.SECOND := INT_TO_USINT(#ISEC);

    #SunDurationTime_R := (#SunSetTime_R - #SunRiseTime_R) / 60.0;

    IF #ActualDateAndTime >= #SunRiseTime AND #ActualDateAndTime <= #SunSetTime THEN
      #IsDay := true;
      #IsNight := false;
      ELSE
      #IsDay := false;
      #IsNight := true;
    END_IF;

    IF #ActualDateAndTime >= (#SunSetTime - 1) THEN
      #PreSet := true;
      ELSE
      #PreSet := false;
    END_IF;
							

Lenguaje SCL – Código de la función NormalizeTo24


  //***********************************************
  // Assign to the FUNCTION the name=NormalizeTo24
  //***********************************************

  // Input parameters
  //-------------------------
  // aTime:       Real
  
  // Return variable
  //-------------------------
  // Ret_Val      Real  

  #NormalizeTo24 := (#aTime - DINT_TO_REAL(FLOOR(#aTime / 24.0)) * 24.0);
							

Lenguaje SCL – Código de la función NormalizeTo180


  //************************************************
  // Assign to the FUNCTION the name=NormalizeTo180
  //************************************************

  // Input parameters
  //-------------------------
  // Angle:       Real

  // Temporary variables
  //-------------------------
  // TempAngle:   Real

  // Return variable
  //-------------------------
  // Ret_Val      Real  


  #TempAngle := "NormalizeTo360"(#Angle);
  IF "NormalizeTo360"(#Angle) > 180.0 THEN
    #TempAngle := "NormalizeTo360"(#Angle) - 360.0;
  END_IF;
  #NormalizeTo180 := #TempAngle;
							

Lenguaje SCL – Código de la función NormalizeTo360


  //************************************************
  // Assign to the FUNCTION the name=NormalizeTo360
  //************************************************

  // Input parameters
  //-------------------------
  // Angle:       Real

  // Return variable
  //-------------------------
  // Ret_Val      Real  

  #NormalizeTo360 := (#Angle - DINT_TO_REAL(FLOOR(#Angle / 360.0)) * 360.0);
							

Últimas recomendaciones sobre esta función para el Seguimiento solar con Siemens 1200 y TIA Portal.

Recuerda llamar al bloque principal dentro de un OB de interrupción fijando el tiempo de interrupción a 1000 milisegundos o 10000 milisegundos.

Esta entrada de Seguimiento solar con Siemens 1200 es original de:

Autor:Bytex Automation  es una compañía italiana con muchos años de experiencia internacional en automatización industrial (especialmente en el sector de acero), webs en tiempo real para análisis y manejo de procesos industriales como manufactura y logistica. Su fortaleza radica en la capacidad de desarrollar sistemas que comunican PLC y bases de datos EPR para producir plataformas web integradas y amigables.

 

Iñigo Gútiez
Iñigo Gútiez

Enseño a programar PLC de Siemens a través de mis cursos.
Más información sobre mi aquí

Puedes seguirme en cualquiera de las siguientes redes sociales.

Filed Under: blog

Reader Interactions

    Deja un comentario Cancelar

    Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

    16 Comentarios

  1. Víctorsjg says

    21 febrero, 2016 at 19:01

    Hola Íñigo tienes el proyecto completo para poder descargarlo, no lo encuentro en la página donde dices que lo has sacado.

    saludos y gracias

    Responder
    • Iñigo Gútiez says

      21 febrero, 2016 at 19:13

      Hola Victor,
      No, no hay proyecto para descargar. Solo el código fuente. Tendrás que copiarlo y generar los bloques.
      Saludos

      Responder
  2. Víctorsjg says

    21 febrero, 2016 at 19:20

    Íñigo, no me queda claro la explicación de comparar el ret_val de la instrucción de extracción de hora local, con w#16#0001

    saludos

    Responder
    • Iñigo Gútiez says

      21 febrero, 2016 at 19:56

      La usa para saber si tiene horario de verano o de invierno. La compara con un «1» en hexadecimal. Si está a uno, es que tiene esa hora de diferencia, y si está a cero, que no. De ahí, que le sume una hora o no tras la comparación.

      Saludos

      Responder
      • Víctorsjg says

        21 febrero, 2016 at 20:05

        No lo entendía porque en las instrucciones de siemens indicaba otra cosa para ret val 0 si no había error.

        saludos

        Responder
        • Iñigo Gútiez says

          21 febrero, 2016 at 20:08

          No exactamente. Sacado de la ayuda de la instrucción:
          Parámetro RET_VAL
          Código de error*
          (W#16#….)
          Descripción
          0000
          Ningún error
          0001
          Ningún error. La hora local se devuelve como horario de verano.

          Saludos

          Responder
          • Víctorsjg says

            21 febrero, 2016 at 20:15

            Lo había mirado en el manual en pdf manual del sistema 1200, no en tia portal

          • Iñigo Gútiez says

            21 febrero, 2016 at 20:16

            En general suele ser así, pero lo mejor siempre es ver la ayuda de cada instrucción.
            Saludos

  3. Jose Antonio says

    28 febrero, 2016 at 18:44

    Hola Iñigo,

    Muy bueno este artículo. Este código o programa se necesita especialmente el ST-1200 o cualquier otro autómata podría dar el mismo resultado, porque no sé si el SCL se podría hacer servir en otros, parece que es como el Visual Basic?, vaya por cierto dispones de autómatas o colaboras con más Voltaje. Quiero hacerme una instalación solar y necesitaría también al menos un autómata. Podrías conseguirme uno que no fuera nuevo y que hiciera el trabajo

    Responder
    • Iñigo Gútiez says

      28 febrero, 2016 at 18:56

      Hola,
      EL SCL es como Pascal, no como VB.
      En cuanto al autómata, si no lo quieres nuevo, tendras que buscarlo en ebay o segunda mano
      Saludos!

      Responder
  4. Javier says

    3 marzo, 2019 at 10:24

    Hola Iñigo
    Estoy intentando poner en práctica el código SCL para generar el FB del seguidor solar, al compilar me da bastantes errores de operandos que no están definidos y que no están en el listado de declaración de variables del ejemplo, la verdad es que no se si debo definir estas variables y con que tipo de dato se tendría que hacer.
    Saludos

    Responder
    • Iñigo Gútiez says

      3 marzo, 2019 at 11:36

      Pues no sé que decirte. Solo compartí en su día el código que facilitaba la empresa italiana. Supongo que por el contexto deberás sacar el tipo de variable que es además de estar haciendo el programa con el PLC 1200 como es el ejemplo.
      Observa, eso sí, que no solamente hay variables en cada bloque, sino un listado al inicio.
      Saludos

      Responder
  5. Ingrid TV says

    7 noviembre, 2019 at 14:48

    Buen día!
    Una pregunta, la serie 1200 maneja diferentes plc. ¿Estaría bien utilizar un plc 1215 ac/dc/rly? ¿O que plc me sugeriría ocupar?

    Responder
    • Iñigo Gútiez says

      7 noviembre, 2019 at 18:12

      Eso lo tienes que decidir tú en función de lo que vayas a hacer, pero con el 1215 no deberías tener demasiados problemas ya que es de los más potentes.

      Responder
      • Ingrid TV says

        14 noviembre, 2019 at 1:44

        Gracias, una duda más, como puedo hacer para direccionar las variables del DB a DBW para que la variable salga como %DB9.DBW es que cuando creo el bloque de datos numero 9 no puedo direccionar para que me salga como anteriormente mencioné.

        Responder
        • Iñigo Gútiez says

          14 noviembre, 2019 at 18:58

          Entiendo que el problema es que tienes marcado el DB como optimizado y deberías ponerlo como no optimizado. Todas esas dudas se resuelven en los cursos.
          Saludos

          Responder
  • Aviso Legal y Política de Privacidad
  • Condiciones de Venta
  • Política de cookies
  • Contacto & Faq
  • Blog

Copyright © 2023 · Programación Siemens · Todos los derechos reservados

· ¿Quién soy? · Misión, Visión y valores