Заход и восход солнца средствами rtc gprs shield v3, оптимизация кода в arduino

Тема в разделе "Флудилка", создана пользователем Андрей Новичок, 26 янв 2020.

Метки:
  1. Здравствуйте, друзья!
    Мне интересно сделать систему освещения, работающую в зависимости от захода и восхода Солнца. В городах уже давно используются системы включения освещения в зависимости от положения солнца, что логично, т.к. это чистая экономия (привет Грете Тумберг:)). Включение освещения планируется сделать с момента типовой побудки и до момента восхода (зимой), а выключение, соответственно, с момента заката и до времени типового отбоя.

    Особая точность не нужна: +/- 20 минут от реального положения светила на горизонте не принципиальны.
    Для RTC используется модуль https://amperka.ru/product/arduino-gprs-shield. Надежды на то, что бесплатные ресурсы завтра не перестанут давать данные по солнцу нет. На просторах Интернета есть много формул для определения захода и восхода в зависимости от географических координат. Ну, в общем, я сделал... Точнее почесал правой ногой левое ухо :). Тригонометрические формулы заняли 67% от доступной памяти Arduino UNO. Не годится.

    Реализовал ранее опробованный вариант сформировать модель более простую, т.к. не требуется особой точности. К сожалению, результат оказался "плачевным". Для более-менее приемлемого качества результата необходимо рассчитывать полином 4-го порядка, как для захода, так и для восхода. Вся эта "хрень" съедает сразу 20% ОЗУ Arduino UNO. Меньше нельзя, т.к. расхождения составляют уже не минуты, а часы. Пенять на библиотеку Sim800l смысла нет, я всё проверил и допилил.
    Код:
    Код (C++):
    void Voshod_Zahod(){
      int day,month,year,minute,second,hour;
      Sim800l.RTCtime(&day,&month,&year,&hour,&minute,&second);
     
      Serial.print("Восход и заход в этот день: ");Serial.print(day);Serial.print('/');Serial.println(month);
      float MyDateTimeDec=month+(day/30.5);//Приведенное к детятичному формату Дата.Время без Года, только ДатаВремя
      Serial.print("Приведенное к DEC число и дата: ");Serial.println(MyDateTimeDec,8);
      //Восход
      //Тренд_Восход=-0,004194985956446*X4+0,113278595835107*X3-0,856456337860489*X2+1,21963461590155*X+8,59986437883103
      float Voshod=-0.004194985956446*pow(MyDateTimeDec,4)+0.113278595835107*pow(MyDateTimeDec,3)-0.856456337860489*pow(MyDateTimeDec,2)+1.21963461590155*MyDateTimeDec+8.59986437883103;
      Serial.print("Приведенное к DEC время Восхода: ");Serial.println(Voshod,8);
      //Заход
      //Тренд_Заход=0,00487951793215*X4-0,131119309343408*X3+1,0109280590299*X2-1,79568491365665*x+17,3755512156507
      float Zahod=0.00487951793215*pow(MyDateTimeDec,4)-0.131119309343408*pow(MyDateTimeDec,3)+1.0109280590299*pow(MyDateTimeDec,2)-1.79568491365665*MyDateTimeDec+17.3755512156507;
      Serial.print("Приведенное к DEC время Захода: ");Serial.println(Zahod,8);
      Serial.println("-------------------------------");
     
    }
    Пример результата вычисления из консоли на сегодня.
    Данные модели на PC для сравнения на 25/1:
    В принципе, как писал выше, даже такая точность устраивает. Но модель на Arduino жрёт ресурсы, чего хотелось бы избежать. Чего только не делал: например, оставлял в модели только зимние месяцы, когда задача наиболее актуальна, - уменьшить вычисления не представляется возможным.

    У меня есть практика работы на PC под приложения MS, когда пришлось делать из строк цифровые отпечатки и далее работать с ними в ОЗУ в виде больших массивов, но на платформе Arduino не годится.

    В общем, нужна помощь от сообщества, даже не сколько по оптимизации приведённого кода, сколько вообще по методике его оптимизации в принципе. Работа с картой или запросы на сервера не устраивают. Нужно простое, понятное решение по минимизации затрат на эти полиномы.
     

    Вложения:

  2. ИгорьК

    ИгорьК Гуру


    Берёшь Sonoff BASIC, подключается к бесплатному серверу погоды https://www.weatherbit.io/, получаешь значения текущего времени, времени захода и восхода, включаешь и выключаешь свет как нравится.

    Извиняюсь. Не заметил важного замечания.

    Я когда слово "сделать" вижу - реагирую. Но в данном случае, видимо, "сделать" - не главное.
     
    SergeiL нравится это.
  3. Интернет бывает время от времени.
     
  4. ИгорьК

    ИгорьК Гуру

    Раз в неделю достаточно для вашей точности.
     
  5. ИгорьК

    ИгорьК Гуру

    Вот смотрите, там только ESP-8266 и дисплей. Точность достаточная. Добавьте анализ данных о солнце, управление пином - и у вас включение света.
     
  6. Игорь, низкий Вам поклон за Ваши посты! Но Вы предлагаете что-то купить, в данном случае услуги связи или компоненты.
    Зачем платить деньги, когда есть мозги?
    Кадушка.jpg
    Вот давайте представим, что мы моемся в бане: в парную залили настой из мяты и настой из еловых иголок. Пар аж бьёт ключом! Затем мы оба выходим и походим каждый к своей кадушке. Кадушки висят на стене, заполненные ледяной водой. Ваша - с сенсорным управлением, фиксацией местоположения потребителя, прочими датчиками и приводом, опрокидывающим кадушку с ледяной водой на потребителя. А у меня кадушка с верёвочкой, - потянул и вода льётся. Но она льётся тогда, когда я хочу, а у Вас - по алгоритму.
    Мой вопрос, вообще-то, довольно существенный и скорее относится к С++ и использованию архитектуры Arduino.
     
  7. ИгорьК

    ИгорьК Гуру

    "Запутала ты меня, Алиса".
    ИМХО, старайтесь писать так, чтобы было понятно уборщице, что вам надо. По крайней мере я так всегда требовал от юристов, когда ими рулил.
     
  8. Меня интересует разумное объяснение или методика того, как можно сократить вычисления, уменьшив использование ОЗУ путём перевода одного пространства числ в другое пространство чисел с сохранением или допустимым отклонением по результату.
     
  9. DetSimen

    DetSimen Guest

    в целых считай.
     
    SergeiL и b707 нравится это.
  10. b707

    b707 Гуру

    я вижу два варианта решения проблемы

    1. Программный - расчитать время восходов и закатов на "большом компе" , составить упакованную табличку и залить ее в Прогмем. Уверен, что при ошибке до 10 минут уложусь в килобайт с запасом - это примерно 3% флеша на Уно

    2. аппаратный - вместо теоретического расчета времени заката и восхода поставить на ардуину датчик освещенности и включать освещение по наступлению реальной темноты, а не "теоретической". Цена такого датчика - доллар, а работать будет куда лучше теории, так как освещение зависит не только от астрономического времени, но и от погоды...
     
    SergeiL, Daniil и DetSimen нравится это.
  11. b707

    b707 Гуру

    разовью мысль с табличкой.
    Даже если подойти к кодированию времени тупо раз в 10 минут - получаем всего 6* 24 = 144 значений в сутки. То есть время восхода или заката данного дня легко можно хранить в одном байте. Итого 365 восходов и 365 закатов за год - чуть больше 730 байт. ВСЕГО.

    Если же учесть, что изменение времени восхода между соседними датами редко превышает 3 минуты в сутки - соответвенно можно хранить данные не на каждый день, а например одно значение на 3 дня. Итого имеем порядка 250 байт -менее 1% доступного флеша.

    И о чем тут вообще говорить?
     
    ИгорьК, DetSimen и Daniil нравится это.
  12. Это я хочу, не знаю как.
     
  13. Daniil

    Daniil Гуру

    Если все же решите выкидывать деньги, то лучше в такую штуку, та же ардуина, но с большими вычислительными возможностями (ключевые слова ARM и 32-разряда).
    А теперь по делу.
    Uno это atmega328 - 8-бит. Вычисления с числами с плавающей зпт (floatы) для неё костыль, поэтому нужно все перевести в целые числа.
    Операции умножения и деления стараться свести к умножению/делению на числа степени 2. Для целых числел умножение на 2^x эквивалентно сдвигу влево на х. Деление - вправо.
    Трансцендентные функции (тригонометрия/логарифмы) нужно перевести к табличному виду. Т.е. нужно занести в память таблицу синуса, допустим от 0 до 2пи. А в самой функции (my_sin) вычислять индекс таблицы.
    Все формулы нужно будет перенормировать к масштабу целых чисел.

    Хотя варианты выше мне тоже нравятся.
     
  14. Как?
     
  15. DetSimen

    DetSimen Guest

    ты не поверишь, наерна, но четверти периода хватит.
     
    Daniil нравится это.
  16. Daniil

    Daniil Гуру

    Оптимизация! Час ночи, а тут такие вкусные вопросы задают, вот и протупил. Спасибо
     
  17. b707

    b707 Гуру

    а что непонятно то, вы программист или где? :))
     
    DetSimen нравится это.
  18. DetSimen

    DetSimen Guest

    смотря где. у меня 5-06 на часах. голодный кот орёт и подпрыгивает
     
  19. b707

    b707 Гуру

    Кодировать время - например так
    5 старших битов байта - часы от 0 до 23
    3 младших бита - десятки минут, соответвенно от 0 до 5
     
    DetSimen нравится это.
  20. Daniil

    Daniil Гуру

    можно хранить время просто в десятках минут.
    0 => 00.00
    1=> 00.10
    ...
    53 => 08.50
    ...
    238=>23.50
    к такому я и тем более не готов
     
    SergeiL нравится это.