Непонятки при работе с массивом

ЁлыПалы

✩✩✩✩✩✩✩
12 Июл 2021
6
0
Уважаемы профи! Помогите любителю ни разу не программисту с ошибкой, которая возникает при работе с массивом. Хочу в часах помимо времени, выводить время восхода, захода, продолжительности дня и т.п. В скетче создал двумерный массив с информацией по дням. Но при проверке скетча выдается ошибка:

"Скетч использует 16644 байт (51%) памяти устройства. Всего доступно 32256 байт.data section exceeds available space in board
Глобальные переменные используют 12164 байт (593%) динамической памяти, оставляя -10116 байт для локальных переменных. Максимум: 2048 байт."

Когда в строке 406: long sunrise = DatasDays[daySinceNY][0]; я переменную daySinceNY (день с начала года) меняю на любое число (например 192), то все проходит нормально и никаких ошибок не возникает. Когда я пытаюсь его вычислить с помощью функции daySince2000, то при попытке вывести данные в монитор порта строки Serial.println(sunrise); выдается вышеупомянутая ошибка.
Почему-то ей не нравится число получаемое выражением: int daySinceNY = daySince2000(d, m, y) - daySince2000(1, 1, y); // номер дня в году. Хотя с виду, результатом этого выражения тоже является число 192.

Мне тут явно не хватает знаний для работы с массивами.

Создал скетч (во вложении).
 

Вложения

poty

★★★★★★✩
19 Фев 2020
3,233
940
Здесь сразу несколько ошибок.
Максимум: 2048 байт
Ваша цитата? А теперь определите, сколько у Вас занимает массив DatasDays! Подсказка: каждое число типа long занимает 4 байта, а у Вас их 365*8!
 
  • Лойс +1
Реакции: Nikanor

ЁлыПалы

✩✩✩✩✩✩✩
12 Июл 2021
6
0
Спасибо большое за ответ! Но почему тогда если я пишу:
DatasDays[192][0], то все работает как мне надо (12 июля - 192 это день в году) и при компиляции выдается красивое сообщение: "
Скетч использует 5054 байт (15%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 458 байт (22%) динамической памяти, оставляя 1590 байт для локальных переменных. Максимум: 2048 байт."
а если вместо DatasDays[daySinceNY][0], то возникает ошибка, хотя daySinceNY тоже равно 192, но уже является следствием вычисления.
Причем я этот массив делал как и глобальным, так и выносил все в отдельную функцию.
 

bort707

★★★★★★✩
21 Сен 2020
3,058
910
Простите, у вас с английским как? вы название функции daysince2000 как перевели? - это не " день с начала года", а " день с начала 2000 года". И поэтому значение этой функции для 12 июля 2021 года - это далеко не 192 , а что-то около 7500...
 

ЁлыПалы

✩✩✩✩✩✩✩
12 Июл 2021
6
0
В скетче и в моем первом посте:
int daySinceNY = daySince2000(d, m, y) - daySince2000(1, 1, y);
результатом является 192
 

bort707

★★★★★★✩
21 Сен 2020
3,058
910
Можете процитировать в сообщении, как описан массив? Ваше вложение у меня не открывается.
А лучше , если код не больше сотни строк - вставьте код в сообщение в теги
 

ЁлыПалы

✩✩✩✩✩✩✩
12 Июл 2021
6
0
Оформи код соответствующим тэгом
#include <Wire.h>
#include "RTClib.h"
RTC_DS3231 rtc;

void setup() {

Serial.begin(9600);

if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}

if (rtc.lostPower()) {
Serial.println("RTC lost power, let's set the time!");
// When time needs to be set on a new device, or after a power loss, the
// following line sets the RTC to the date & time this sketch was compiled
}

long DatasDays[365][8] = {
{32670,56761,24060,1,91,540,26560,62871},
{32648,56838,24180,1,100,660,26551,62935},
{32621,56920,24240,1,108,720,26539,63001},
{32590,57005,24360,1,116,840,26524,63070},
...
{32704,56601,23880,1,72,360,26567,62739},
{32692,56669,23940,1,81,420,26566,62796}
};

DateTime now = rtc.now();

int y;
byte m;
byte d;
byte h;
byte mnt;
byte sec;

y = now.year();
m = now.month();
d = now.day();

DateTime dt0 (y, 1, 1, 0, 0, 0);
DateTime dt1 (y, m, d, 0, 0, 0);
TimeSpan ts = dt1 - dt0;

int daySinceNY = ts.days();

long sunrise = DatasDays[daySinceNY ][0];

convertSecToTime(sunrise, h, mnt, sec);

Serial.println(ts1);
Serial.println(sunrise);
Serial.println(h);
Serial.println(mnt);
Serial.println(sec);

}

void loop() {
// put your main code here, to run repeatedly:

}

void convertSecToTime(long Time,byte &h,byte &mnt,byte &sec){
h = Time/3600;
mnt = (Time - h*3600)/60;
sec = Time - h*3600 - mnt*60;
}

Здесь я уже высчитываю номер дня в году, покопавшись в функционале библиотеки (который тоже выдает те же 192)
 

Вложения

bort707

★★★★★★✩
21 Сен 2020
3,058
910
Я вас просил показать, как описан массив. А вы мне что пишете?
Впрочем, уже не надо, я уже смог скачать ваш код.
Смотрите, строка 4, ваш массив задан как
C++:
long DatasDays[365][8]
это означает массив размером 365х8 с элементами типа лонг.
Вы считать умеете? Или калькулятор возьмите... Такой массив требует 365*8*4 = 11680 байт. А у вашей ардуинки 2048 байт всего. Так чего ж вы хотите от нее? Конечно это ни за что не скомпилируется
 
  • Лойс +1
Реакции: ЁлыПалы

ЁлыПалы

✩✩✩✩✩✩✩
12 Июл 2021
6
0
Извините, конечно, я полный нуб в этом, но почему тогда все прекрасно компилируется, считается и скетч работает полностью как мне надо, если я пишу не DatasDays[daySinceNY][0], а день 192 прописываю вручную DatasDays[192][0]:
"
Скетч использует 5054 байт (15%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 458 байт (22%) динамической памяти, оставляя 1590 байт для локальных переменных. Максимум: 2048 байт."

Во вложении скриншоты, все отличие во всем скетче только в одном параметре
 

Вложения

Геннадий П

★★★★★★✩
14 Апр 2021
1,970
632
45
@ЁлыПалы, Это оптимизация компилятора.
Если ты используешь только одну ячейку массива, то он все остальные просто выкидывает. А если обращаешься через переменную, которая заранее неизвестна, то оставляет весь массив, т.к. он заранее не знает к которой ячейке ты будешь обращаться.
 
  • Лойс +1
Реакции: bort707

bort707

★★★★★★✩
21 Сен 2020
3,058
910
На картинках не видно, но я правильно понял, что в обоих случаях описание огромного массива в начале кода осталось?
Это сложнее, но могу предположить. Дело в оптимизации. Ваш массив используется в коде в одном единственном месте. Когда вы ставите в выражение
C++:
  long sunrise = DatasDays[daySinceNY][0];
константу, например 192 - компилятор видит, что из всего массива вам нужно только это значение. Весь остальной массив из кода выкидывается и памяти хватает. Если же тут в выражении переменная, компилятор не знает, какая часть массива понадобится и выкинуть его не может. Но это мое предположение, может кто из более опытных поправит.

В любом случае, как вывод - то что строчка с константой 192 компилируется, для практики значения не имеет. Как бы вы не вводили массив - переменными или построчно - 365 строчек по 8 лонгов в память ардуино не влезут.
 
  • Лойс +1
Реакции: ЁлыПалы

Геннадий П

★★★★★★✩
14 Апр 2021
1,970
632
45
Проще через алгоритм, ссылку на который я привел. Если в нем широту-долготу записать в коде как константы, то он скорее всего бОльшую часть оптимизирует и вычисления сократятся. Да и эти вычисления нужны только раз в сутки, поэтому над скоростью работы алгоритма можно не заморачиваться.
 
  • Лойс +1
Реакции: ЁлыПалы

bort707

★★★★★★✩
21 Сен 2020
3,058
910
Большое спасибо всем откликнувшимся! Теперь стало всё понятно.
добавлю - если хотите все-таки запихнуть ваш массив в ардуино - почитайте про прогмем. Это как раз ваш случай, потому что весь массив константный - т.е. задается заранее и менятся в программе не будет.
 
  • Лойс +1
Реакции: ЁлыПалы