├── .gitattributes ├── .github └── workflows │ └── tg-send.yml ├── LICENSE ├── README.md ├── README_EN.md ├── doc └── angles.png ├── examples └── demo │ └── demo.ino ├── keywords.txt ├── library.properties └── src └── SunPosition.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/tg-send.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Telegram Message 3 | on: 4 | release: 5 | types: [published] 6 | jobs: 7 | build: 8 | name: Send Message 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: send telegram message on push 12 | uses: appleboy/telegram-action@master 13 | with: 14 | to: ${{ secrets.TELEGRAM_TO }} 15 | token: ${{ secrets.TELEGRAM_TOKEN }} 16 | disable_web_page_preview: true 17 | message: | 18 | ${{ github.event.repository.name }} v${{ github.event.release.tag_name }} 19 | ${{ github.event.release.body }} 20 | https://github.com/${{ github.repository }} 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Alex 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![latest](https://img.shields.io/github/v/release/GyverLibs/SunPosition.svg?color=brightgreen)](https://github.com/GyverLibs/SunPosition/releases/latest/download/SunPosition.zip) 2 | [![PIO](https://badges.registry.platformio.org/packages/gyverlibs/library/SunPosition.svg)](https://registry.platformio.org/libraries/gyverlibs/SunPosition) 3 | [![Foo](https://img.shields.io/badge/Website-AlexGyver.ru-blue.svg?style=flat-square)](https://alexgyver.ru/) 4 | [![Foo](https://img.shields.io/badge/%E2%82%BD%24%E2%82%AC%20%D0%9F%D0%BE%D0%B4%D0%B4%D0%B5%D1%80%D0%B6%D0%B0%D1%82%D1%8C-%D0%B0%D0%B2%D1%82%D0%BE%D1%80%D0%B0-orange.svg?style=flat-square)](https://alexgyver.ru/support_alex/) 5 | [![Foo](https://img.shields.io/badge/README-ENGLISH-blueviolet.svg?style=flat-square)](https://github-com.translate.goog/GyverLibs/SunPosition?_x_tr_sl=ru&_x_tr_tl=en) 6 | 7 | [![Foo](https://img.shields.io/badge/ПОДПИСАТЬСЯ-НА%20ОБНОВЛЕНИЯ-brightgreen.svg?style=social&logo=telegram&color=blue)](https://t.me/GyverLibs) 8 | 9 | # SunPosition 10 | Библиотека для определения положения солнца по геолокации и времени 11 | - Берёт широту, долготу и unix время 12 | - Выдаёт угол по азимуту, угол возвышения и склонения солнца 13 | 14 | ### Совместимость 15 | Совместима со всеми Arduino платформами (используются Arduino-функции) 16 | 17 | ## Содержание 18 | - [Установка](#install) 19 | - [Инициализация](#init) 20 | - [Использование](#usage) 21 | - [Пример](#example) 22 | - [Версии](#versions) 23 | - [Баги и обратная связь](#feedback) 24 | 25 | 26 | ## Установка 27 | - Библиотеку можно найти по названию **SunPosition** и установить через менеджер библиотек в: 28 | - Arduino IDE 29 | - Arduino IDE v2 30 | - PlatformIO 31 | - [Скачать библиотеку](https://github.com/GyverLibs/SunPosition/archive/refs/heads/main.zip) .zip архивом для ручной установки: 32 | - Распаковать и положить в *C:\Program Files (x86)\Arduino\libraries* (Windows x64) 33 | - Распаковать и положить в *C:\Program Files\Arduino\libraries* (Windows x32) 34 | - Распаковать и положить в *Документы/Arduino/libraries/* 35 | - (Arduino IDE) автоматическая установка из .zip: *Скетч/Подключить библиотеку/Добавить .ZIP библиотеку…* и указать скачанный архив 36 | - Читай более подробную инструкцию по установке библиотек [здесь](https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA) 37 | ### Обновление 38 | - Рекомендую всегда обновлять библиотеку: в новых версиях исправляются ошибки и баги, а также проводится оптимизация и добавляются новые фичи 39 | - Через менеджер библиотек IDE: найти библиотеку как при установке и нажать "Обновить" 40 | - Вручную: **удалить папку со старой версией**, а затем положить на её место новую. "Замену" делать нельзя: иногда в новых версиях удаляются файлы, которые останутся при замене и могут привести к ошибкам! 41 | 42 | 43 | 44 | ## Инициализация 45 | ```cpp 46 | // инициализировать без расчёта 47 | SunPosition pos; 48 | 49 | // указать широту (градусы), долготу (градусы), unix время (секунды), будет выполнен расчёт 50 | SunPosition(latitude, longitude, unix); 51 | SunPosition(latitude, longitude, unix, gmt); // + часовой пояс в часах или минутах 52 | ``` 53 | 54 | 55 | ## Использование 56 | ```cpp 57 | // выполнить расчёт, указать широту (градусы), долготу (градусы), unix время (секунды) 58 | void compute(float latitude, float longitude, uint32_t unix); 59 | 60 | // выполнить расчёт, указать широту (градусы), долготу (градусы), unix время (секунды), часовой пояс в часах или минутах 61 | void compute(float latitude, float longitude, uint32_t unix, int16_t gmt); 62 | 63 | int sunrise(); // время рассвета, в минутах от начала дня по локальному времени 64 | int noon(); // полдень, в минутах от начала дня по локальному времени 65 | int sunset(); // время заката, в минутах от начала дня по локальному времени 66 | int daylight(); // длительность светового дня, в минутах 67 | float altitude(); // угол возвышения 68 | float declination(); // угол склонения 69 | float zenith(); // угол зенита в полдень 70 | float azimuth(); // азимут солнца, от севера по часовой стрелке 71 | int azimuthMin(); // азимут рассвета 72 | int azimuthMax(); // азимут заката 73 | int angle180(); // азимут, масштабированный в диапазон 0-180 градусов для поворота солнечной панели (летом 0..180, зимой 50.. 130) 74 | int angle90(); // азимут, масштабированный в диапазон -90..90 градусов для поворота солнечной панели (летом -90..90, зимой -20.. 20) 75 | ``` 76 | 77 | - Широту и долготу места можно взять из любых карт (Яндекс, Google) 78 | - Unix время можно взять из любого источника реального времени (RTC, NTP), а также конвертировать из даты и времени при помощи библиотеки [UnixTime](https://github.com/GyverLibs/UnixTime) 79 | 80 | ![diagram](/doc/angles.png) 81 | - **Угол склонения** - угол от направления на солнце в точке равноденствия, меняется в течение года. Сам угол равноденствия равен `90 - широта` 82 | - **Азимут** - направление на солнце по горизонтали, считается от направления на Север по часовой стрелке 83 | - **Возвышение** - направление на солнце по вертикали от горизонта 84 | 85 | 86 | ## Пример 87 | ```cpp 88 | #include 89 | 90 | void setup() { 91 | Serial.begin(9600); 92 | SunPosition sun(55.75, 37.62, 1658325600); 93 | //sun.compute(55.75, 37.62, 1658325600); 94 | Serial.println(sun.altitude()); 95 | Serial.println(sun.azimuth()); 96 | Serial.println(sun.declination()); 97 | } 98 | 99 | void loop() { 100 | } 101 | ``` 102 | 103 | 104 | ## Версии 105 | - v1.0 106 | - v1.1 - полностью переписаны уравнения, добавлен вывод времени и азимута заката/рассвета и другие полезные углы (см. доку) 107 | 108 | 109 | ## Баги и обратная связь 110 | При нахождении багов создавайте **Issue**, а лучше сразу пишите на почту [alex@alexgyver.ru](mailto:alex@alexgyver.ru) 111 | Библиотека открыта для доработки и ваших **Pull Request**'ов! 112 | 113 | При сообщении о багах или некорректной работе библиотеки нужно обязательно указывать: 114 | - Версия библиотеки 115 | - Какой используется МК 116 | - Версия SDK (для ESP) 117 | - Версия Arduino IDE 118 | - Корректно ли работают ли встроенные примеры, в которых используются функции и конструкции, приводящие к багу в вашем коде 119 | - Какой код загружался, какая работа от него ожидалась и как он работает в реальности 120 | - В идеале приложить минимальный код, в котором наблюдается баг. Не полотно из тысячи строк, а минимальный код 121 | -------------------------------------------------------------------------------- /README_EN.md: -------------------------------------------------------------------------------- 1 | This is an automatic translation, may be incorrect in some places. See sources and examples! 2 | 3 | # Sunposition 4 | Library for determining the position of the Sun by geolocation and time 5 | - takes breadth, longitude and unix time 6 | - gives an angle by azimuth, the angle of elevation and declination of the sun 7 | 8 | ## compatibility 9 | Compatible with all arduino platforms (used arduino functions) 10 | 11 | ## Content 12 | - [installation] (# Install) 13 | - [initialization] (#init) 14 | - [use] (#usage) 15 | - [Example] (# Example) 16 | - [versions] (#varsions) 17 | - [bugs and feedback] (#fedback) 18 | 19 | 20 | ## Installation 21 | - The library can be found by the name ** suposition ** and installed through the library manager in: 22 | - Arduino ide 23 | - Arduino ide v2 24 | - Platformio 25 | - [download the library] (https://github.com/gyverlibs/sunposition/archive/refs/heads/main.zip) .Zip archive for manual installation: 26 | - unpack and put in * C: \ Program Files (X86) \ Arduino \ Libraries * (Windows X64) 27 | - unpack and put in * C: \ Program Files \ Arduino \ Libraries * (Windows X32) 28 | - unpack and put in *documents/arduino/libraries/ * 29 | - (Arduino id) Automatic installation from. Zip: * sketch/connect the library/add .Zip library ... * and specify downloaded archive 30 | - Read more detailed instructions for installing libraries [here] (https://alexgyver.ru/arduino-first/#%D0%A3%D1%81%D1%82%D0%B0%BD%D0%BE%BE%BE%BED0%B2%D0%BA%D0%B0_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA) 31 | ### Update 32 | - I recommend always updating the library: errors and bugs are corrected in the new versions, as well as optimization and new features are added 33 | - through the IDE library manager: find the library how to install and click "update" 34 | - Manually: ** remove the folder with the old version **, and then put a new one in its place.“Replacement” cannot be done: sometimes in new versions, files that remain when replacing are deleted and can lead to errors! 35 | 36 | 37 | 38 | ## initialization 39 | `` `CPP 40 | // initialize without calculation 41 | SunPounion POS; 42 | 43 | // indicate latitude (degrees), longitude (degrees), unix time (seconds), a calculation will be performed 44 | SunPounion (Latitude, Longitude, Unix); 45 | SunPounion (Latitude, Longitude, Unix, GMT);// + hourly belt in hours or minutes 46 | `` ` 47 | 48 | 49 | ## Usage 50 | `` `CPP 51 | // perform the calculation, indicate the latitude (degrees), longitude (degrees), unix time (seconds) 52 | Void Compute (Float Latitude, Float Longitude, Uint32_T Unix); 53 | 54 | // perform the calculation, specify the latitude (degrees), longitude (degrees), unix time (seconds), an hourly belt in hours or minutes 55 | Void Compute (Float Latitude, Float Longitude, Uint32_T Unix, Int16_T GMT); 56 | 57 | int sunrise ();// Dawn time, minutes from the beginning of the day in local time 58 | int noon ();// Half, in minutes from the beginning of the day in local time 59 | int sunset ();// Sunset time, minutes from the beginning of the day in local time 60 | int daylight ();// Duration of daylight hours, in minutes 61 | Float altitude ();// Avoor angle 62 | Float Decline ();// angle of declension 63 | Float Zenith ();// Zenit angle at noon 64 | Float Azimuth ();// Azimuth of the Sun, from the north clockwise 65 | int Azimuthmin ();// Azimuth of Dawn 66 | int Azimuthmax ();// Azimuth of sunset 67 | int angle180 ();// azimuth, scaled in the range 0-180 degrees DCranberries of turning the solar panel (in summer 0..180, in winter 50 .. 130) 68 | int angle90 ();// Azimuth, scaled in the range -90..90 degrees for turning the solar panel (in summer -90..90, in winter -20 .. 20) 69 | `` ` 70 | 71 | - The latitude and longitude can be taken from any cards (Yandex, Google) 72 | - Unix time can be taken from any real time source (RTC, NTP), and also converted from the date and time using the library [unixtime] (https://github.com/gyverlibs/unixtime) 73 | 74 | ! [Diagram] (/doc/angles.png) 75 | - ** The angle of declension ** - the angle from the direction to the sun at the point of the equinox, changes during the year.The angle of equinox itself is `90 - LATE` 76 | - ** azimuth ** - a direction in the sun is horizontally, it is considered from the direction to the north clockwise 77 | - ** elevation ** - a direction in the sun vertically from the horizon 78 | 79 | 80 | ## Example 81 | `` `CPP 82 | #include 83 | 84 | VOID setup () { 85 | Serial.Begin (9600); 86 | SunPounion Sun (55.75, 37.62, 1658325600); 87 | //sun.computE(55.75, 37.62, 1658325600); 88 | Serial.println (sun.altite ()); 89 | Serial.println (sun.azimuth ()); 90 | Serial.println (sun.Decline ()); 91 | } 92 | 93 | VOID loop () { 94 | } 95 | `` ` 96 | 97 | 98 | ## versions 99 | - V1.0 100 | - V1.1 - the equations are completely rewritten, the output of the time and the azimuth of sunset/dawn and other useful angles (see Doku) have been added 101 | 102 | 103 | ## bugs and feedback 104 | Create ** Issue ** when you find the bugs, and better immediately write to the mail [alex@alexgyver.ru] (mailto: alex@alexgyver.ru) 105 | The library is open for refinement and your ** pull Request ** 'ow! 106 | 107 | When reporting about bugs or incorrect work of the library, it is necessary to indicate: 108 | - The version of the library 109 | - What is MK used 110 | - SDK version (for ESP) 111 | - version of Arduino ide 112 | - whether the built -in examples work correctly, in which the functions and designs are used, leading to a bug in your code 113 | - what code has been loaded, what work was expected from it and how it works in reality 114 | - Ideally, attach the minimum code in which the bug is observed.Not a canvas of a thousand lines, but a minimum code -------------------------------------------------------------------------------- /doc/angles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GyverLibs/SunPosition/f4b8d98fcc0ec3708846b9bd37d9344fbf755b39/doc/angles.png -------------------------------------------------------------------------------- /examples/demo/demo.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void setup() { 4 | Serial.begin(9600); 5 | SunPosition sun(55.75, 37.62, 1658325600); 6 | //sun.compute(55.75, 37.62, 1658325600); 7 | Serial.println(sun.altitude()); 8 | Serial.println(sun.azimuth()); 9 | Serial.println(sun.declination()); 10 | } 11 | 12 | void loop() { 13 | } -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For SunPosition 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | SunPosition KEYWORD1 9 | SP_PRECISE KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | compute KEYWORD2 15 | altitude KEYWORD2 16 | azimuth KEYWORD2 17 | azimuthMin KEYWORD2 18 | azimuthMax KEYWORD2 19 | declination KEYWORD2 20 | angle180 KEYWORD2 21 | angle90 KEYWORD2 22 | zenith KEYWORD2 23 | sunrise KEYWORD2 24 | noon KEYWORD2 25 | sunset KEYWORD2 26 | daylight KEYWORD2 27 | 28 | ####################################### 29 | # Constants (LITERAL1) 30 | ####################################### -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=SunPosition 2 | version=1.2.0 3 | author=AlexGyver 4 | maintainer=AlexGyver 5 | sentence=Library for tracking Sun position by location and time for Arduino 6 | paragraph=Library for tracking Sun position by location and time for Arduino 7 | category=Data Processing 8 | url=https://github.com/GyverLibs/SunPosition 9 | architectures=* 10 | -------------------------------------------------------------------------------- /src/SunPosition.h: -------------------------------------------------------------------------------- 1 | /* 2 | Библиотека для определения положения солнца по геолокации и времени 3 | Документация: 4 | GitHub: https://github.com/GyverLibs/SunPosition 5 | Возможности: 6 | - Берёт широту, долготу и unix время 7 | - Выдаёт угол по азимуту, угол возвышения и склонения солнца 8 | 9 | AlexGyver, alex@alexgyver.ru 10 | https://alexgyver.ru/ 11 | MIT License 12 | 13 | v1.1 - полностью переписаны уравнения, добавлен вывод времени и азимута заката/рассвета и другие полезные углы (см. доку) 14 | */ 15 | 16 | /* 17 | Источники: 18 | Astronomical Almanac p C2 19 | https://www.astrogreg.com/snippets/equationoftime-simple.html 20 | https://www.itacanet.org/the-sun-as-a-source-of-energy/part-3-calculating-solar-angles/ 21 | https://webcms3.cse.unsw.edu.au/ENGG1811/16s1/forums/514357 22 | https://gml.noaa.gov/grad/solcalc/calcdetails.html 23 | нужен double! http://users.electromagnetic.net/bu/astro/sunrise-set.php 24 | 25 | для проверки https://www.suncalc.org/ 26 | http://www.geoastro.de/astro/suncalc/index.htm 27 | */ 28 | 29 | #ifndef _SunPosition_h 30 | #define _SunPosition_h 31 | #include 32 | 33 | struct SunPosition { 34 | // просто создать 35 | SunPosition() {} 36 | 37 | // указать широту (градусы), долготу (градусы), unix время (секунды), часовой пояс в часах или минутах. Будет выполнен расчёт 38 | SunPosition(float lat, float lon, uint32_t unix, int16_t gmt = 0) { 39 | compute(lat, lon, unix, gmt); 40 | } 41 | 42 | // выполнить расчёт, указать широту (градусы), долготу (градусы), unix время (секунды), часовой пояс в часах или минутах 43 | void compute(float lat, float lon, uint32_t unix, int16_t gmt = 0) { 44 | lat = radians(lat); 45 | float hours = (unix % 86400ul) / 86400.0; // decimal hours 46 | #ifndef SP_PRECISE 47 | int day = fmod(unix / 86400.0, 365.25); 48 | float t = radians(279.342 + 0.985647 * day); // temp 49 | float eqTime = (-104.9 * sin(t) + 596.2 * sin(2 * t) + 4.3 * sin(3 * t) - 12.7 * sin(4 * t) - 429.3 * cos(t) - 2.0 * cos(2 * t) + 19.3 * cos(3 * t)) / 60.0; // time equation 50 | t = (day + hours / 24 - 1.5) * TWO_PI / 365; // temp 51 | decl = 0.006918 - 0.4 * cos(t) + 0.070257 * sin(t) - 0.006758 * cos(t * 2) + 0.000907 * sin(t * 2) - 0.002697 * cos(t * 3) + 0.00148 * sin(t * 3); // declination 52 | #else 53 | float JulCent = (unix / 86400.0 - 10957.5) / 36525.0; // Julian Century 54 | float GeomMeanLong = radians(fmod(280.46646 + JulCent * (36000.76983 + JulCent * 0.0003032), 360)); // Geom Mean Long Sun 55 | float GeomMeanAnom = radians(357.52911 + JulCent * (36000 - 0.0001537 * JulCent)); // Geom Mean Anom Sun 56 | float EccEart = 0.016708634 - JulCent * (0.000042037 + 0.0000001267 * JulCent); // Eccent Earth Orbit 57 | float SunEqCtr = radians(sin(GeomMeanAnom) * (1.914602 - JulCent * (0.004817 + 0.000014 * JulCent)) + sin(2 * GeomMeanAnom) * (0.019993 - 0.000101 * JulCent) + sin(3 * GeomMeanAnom) * 0.000289); // Sun Eq of Ctr 58 | float SunApp = GeomMeanLong + SunEqCtr - 0.0001 - 0.00008 * sin(radians(125.04 - 1934.136 * JulCent)); // Sun App Long 59 | float MeanOblq = 23 + (26 + ((21.448 - JulCent * (46.815 + JulCent * (0.00059 - JulCent * 0.001813)))) / 60.0) / 60.0; // Mean Obliq Ecliptic 60 | float ObliqCor = radians(MeanOblq + 0.00256 * cos(radians(125.04 - 1934.136 * JulCent))); // Obliq Corr 61 | decl = asin(sin(ObliqCor) * sin(SunApp)); // Sun Declin 62 | float y = tan(ObliqCor / 2) * tan(ObliqCor / 2); 63 | float eqTime = 4 * degrees(y * sin(2 * GeomMeanLong) - 2 * EccEart * sin(GeomMeanAnom) + 4 * EccEart * y * sin(GeomMeanAnom) * cos(2 * GeomMeanLong) - 0.5 * y * y * sin(4 * GeomMeanLong) - 1.25 * EccEart * EccEart * sin(2 * GeomMeanAnom)); // Eq of Time (minutes) 64 | #endif 65 | ha = degrees(acos(-0.01454 / (cos(lat) * cos(decl)) - tan(lat) * tan(decl))); // HA sunrise 66 | if (abs(gmt) <= 12) gmt *= 60; // gmt -> minutes 67 | noonT = 720 - 4 * lon - eqTime + gmt; // Solar Noon (min) + gmt 68 | float hrAngl = fmod(hours * 1440 + eqTime + 4 * lon, 1440) / 4; // True Solar Time (min) 69 | hrAngl = hrAngl + (hrAngl < 0 ? 180 : -180); // Hour Angle 70 | zen = acos(sin(lat) * sin(decl) + cos(lat) * cos(decl) * cos(radians(hrAngl))); // Zenith 71 | azm = degrees(acos(((sin(lat) * cos(zen)) - sin(decl)) / (cos(lat) * sin(zen)))); // Azimuth 72 | decl = degrees(decl); 73 | alt = 90 - degrees(zen); 74 | azm = (hrAngl > 0) ? (azm + 180) : (540 - azm); 75 | azm = fmod(azm, 360); 76 | zen = 90 - degrees(lat) + decl; 77 | //angle = round(ha); // 8 * ha * 360 / 60 / 24 / 2 78 | } 79 | 80 | // время рассвета, в минутах от начала дня по локальному времени 81 | int sunrise() { 82 | return noonT - ha * 4; 83 | } 84 | 85 | // полдень, в минутах от начала дня по локальному времени 86 | int noon() { 87 | return noonT; 88 | } 89 | 90 | // время заката, в минутах от начала дня по локальному времени 91 | int sunset() { 92 | return noonT + ha * 4; 93 | } 94 | 95 | // длительность светового дня, в минутах 96 | int daylight() { 97 | return ha * 8; 98 | } 99 | 100 | // угол возвышения 101 | float altitude() { 102 | return alt; 103 | } 104 | 105 | // угол склонения 106 | float declination() { 107 | return decl; 108 | } 109 | 110 | // угол зенита 111 | float zenith() { 112 | return zen; 113 | } 114 | 115 | // азимут солнца, от севера по часовой стрелке 116 | float azimuth() { 117 | return azm; 118 | } 119 | 120 | // азимут рассвета 121 | int azimuthMin() { 122 | return (180 - round(ha)); 123 | } 124 | 125 | // азимут заката 126 | int azimuthMax() { 127 | return (180 + round(ha)); 128 | } 129 | 130 | // азимут, масштабированный в диапазон 0..180 градусов для поворота солнечной панели (летом 0..180, зимой 50.. 130) 131 | int angle180() { 132 | int a = round(ha); 133 | a = map(azm, 180 - a, 180 + a, 90 - min(a, 90), 90 + min(a, 90)); 134 | a = constrain(a, 0, 180); 135 | return a; 136 | } 137 | 138 | // азимут, масштабированный в диапазон -90..90 градусов для поворота солнечной панели (летом -90..90, зимой -20.. 20) 139 | int angle90() { 140 | return angle180() - 90; 141 | } 142 | 143 | float alt = 0, azm = 0, decl = 0, zen = 0, ha = 0; 144 | uint16_t noonT = 0; 145 | }; 146 | 147 | /* 148 | // без оптимизации 149 | float JulDay = unixSecs / 86400.0 + 2440587.5; // Julian day 150 | float JulCent = (JulDay - 2451545.0) / 36525.0; // Julian Century 151 | float GeomMeanLong = fmod(280.46646 + JulCent * (36000.76983 + JulCent * 0.0003032), 360); // Geom Mean Long Sun 152 | float GeomMeanAnom = 357.52911 + JulCent * (35999.05029 - 0.0001537 * JulCent); // Geom Mean Anom Sun 153 | float EccEart = 0.016708634 - JulCent * (0.000042037 + 0.0000001267 * JulCent); // Eccent Earth Orbit 154 | float SunEqCtr = sin(radians(GeomMeanAnom)) * (1.914602 - JulCent * (0.004817 + 0.000014 * JulCent)); // Sun Eq of Ctr 155 | SunEqCtr += sin(2 * radians(GeomMeanAnom)) * (0.019993 - 0.000101 * JulCent); 156 | SunEqCtr += sin(3 * radians(GeomMeanAnom)) * 0.000289; 157 | float SunTrLong = GeomMeanLong + SunEqCtr; // Sun True Long 158 | float SunTrAnom = GeomMeanAnom + SunEqCtr; // Sun True Anom 159 | float SunRad = (1.000001018 * (1.0 - EccEart * EccEart)) / (1 + EccEart * cos(radians(SunTrAnom))); // Sun Rad Vector (AUs) 160 | float SunApp = SunTrLong - 0.00569 - 0.00478 * sin(radians(125.04 - 1934.136 * JulCent)); // Sun App Long 161 | float MeanOblq = 23 + (26 + ((21.448 - JulCent * (46.815 + JulCent * (0.00059 - JulCent * 0.001813)))) / 60.0) / 60.0; // Mean Obliq Ecliptic 162 | float ObliqCor = MeanOblq + 0.00256 * cos(radians(125.04 - 1934.136 * JulCent)); // Obliq Corr 163 | float SunDecl = degrees(asin(sin(radians(ObliqCor)) * sin(radians(SunApp)))); // Sun Declin 164 | float y = tan(radians(ObliqCor / 2)) * tan(radians(ObliqCor / 2)); 165 | float EqTime = 4 * degrees(y * sin(2 * radians(GeomMeanLong)) - 2 * EccEart * sin(radians(GeomMeanAnom)) + 4 * EccEart * y * sin(radians(GeomMeanAnom)) * cos(2 * radians(GeomMeanLong)) - 0.5 * y * y * sin(4 * radians(GeomMeanLong)) - 1.25 * EccEart * EccEart * sin(2 * radians(GeomMeanAnom))); // Eq of Time (minutes) 166 | float HA = degrees(acos(cos(radians(90.833)) / (cos(radians(lat)) * cos(radians(SunDecl))) - tan(radians(lat)) * tan(radians(SunDecl)))); // HA Sunrise 167 | int GMT = 0; 168 | float SunN = 720 - 4 * lon - EqTime + GMT * 60; // Solar Noon (LST) + gmt 169 | float SunR = SunN - HA * 4; // Sunrise Time (LST) + gmt 170 | float SunS = SunN + HA * 4; // Sunset Time (LST) + gmt 171 | float SunL = 8 * HA; // Sunlight Duration (minutes) minutes 172 | float hours = (unixSecs % 86400) / 86400.0; 173 | float TrueSol = fmod(hours * 1440 + EqTime + 4 * lon, 1440); // True Solar Time (min) 174 | float HourAngle = (TrueSol / 4 < 0) ? TrueSol / 4 + 180 : TrueSol / 4 - 180; // Hour Angle 175 | float Zenith = degrees(acos(sin(radians(lat)) * sin(radians(SunDecl)) + cos(radians(lat)) * cos(radians(SunDecl)) * cos(radians(HourAngle)))); 176 | float Elev = 90 - Zenith; 177 | float Azim = degrees(acos(((sin(radians(lat)) * cos(radians(Zenith))) - sin(radians(SunDecl))) / (cos(radians(lat)) * sin(radians(Zenith))))); 178 | if (HourAngle > 0) Azim = Azim + 180; 179 | else Azim = 540 - Azim; 180 | Azim = fmod(Azim, 360); 181 | */ 182 | #endif 183 | --------------------------------------------------------------------------------