Проблема - не достаточно памяти Arduino

Рейтинг: -4Ответов: 1Опубликовано: 15.06.2023

Я создал скетч для часы, каждого сегмента 9 ws2812b лента. Глобальные переменные используют 2352 байт (114%) динамической памяти, оставляя -304 байт для локальных переменных. Максимум: 2048 байт. Проблема - недостаточно памяти.
прочитайте http://www.arduino.cc/en/Guide/Troubleshooting#size
Ошибка компиляции для платы Arduino Uno.
Помогите пожалуйста - как уменьшить используемый объем памяти?

// library 
#include <DS3232RTC.h> 
#include <TimeLib.h> 
#include <Time.h> 
#include <Wire.h> 
#include <FastLED.h> 
//library 

// uzgarmaslar 
#define NUM_LEDS 380 
#define COLOR_ORDER GRB 
#define LED_PIN 12 
#define DST_PIN 5 
#define MIN_PIN 4 
#define HUR_PIN 2 
#define CHANGE_CLR_PIN 8 
#define BRI_PIN 3 
// uzgarmaslar

byte digits[10][63] = { 
    {0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, // Digit 0 
    {0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1}, // Digit 1 
    {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0}, // Digit 2

};  

void PrintNumber(int number,int beginPosition)
{ 
    for(int i=beginPosition; i < beginPosition+63; i++)
    { 
        int arrayPos = i - beginPosition; 
        if(digits[number][arrayPos] == 1)
            { leds[i] = defaultColor; }
        else
            { leds[i] = 0x000000; } 
    } 
}
void OffLights()
{ 
    for(int i=0; i< NUM_LEDS; i++)
        { leds[i] = 0x000000; } 
}
void dotSwitch()
{ 
    tmElements_t Now; 
    RTC.read(Now); 
    int second = Now.Second; 
    if (second % 2==0) 
    { 
        leds[126] = defaultColor; 
        leds[127] = defaultColor; 
    } 
    else 
    { 
        leds[126] = 0x000000; 
        leds[127] = 0x000000; 
    }; 
} 

Ответы

▲ 1

Замечания по вопросу:

  1. Код приведен не весь
  2. Что такое массив leds[]? При анализе кода представляется что это массив из 380 элементов, каждый из которых занимает 3 байта. Т.е. всего 1140 байт.
  3. В вашем фрагменте кода переменных массив digits[10][63] - 630 байт и 14 байт - макросы, которые транслируются в int. Т.е. вероятно где-то ещё есть переменные, которые вы не показали здесь.

Теперь по вариантам уменьшения памяти:
Попробуйте использовать побитовое хранение информации вместо массива byte digits[10][63]. Тогда он будет выглядеть как byte digits[10][8]. И занимать будет не 630 байт а 80.

byte digits[10][8] = { 
    { 0b00000000, 0b00111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111}, // Digit 0

// или если бинарная запись чисел не поддерживается
byte digits[10][8] = { 
    { 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // Digit 0

Из описания модели памяти Arduino:

Неизменяемые строки и данные во время работы скетча можно хранить во флеш-памяти. Для этого необходимо использовать ключ PROGMEM.

Скорее всего что-то можно сделать с массивом leds[], если знать как он объявлен и для чего вообще нужен. Какой тип у массива leds[] и defaultColor? Просто странная размерность - 3 байта leds[i] = 0x000000;. Судя по всему у вас массив leds[380] из 380 светодиодов. И в каждом элементе вы храните его цвет (3 байта). Но судя по коду, реально вы используете только 2 цвета - 0x00 и defaultColor (светит/не светит). Тогда зачем хранить цвет и использовать (наверное!) 3 байта памяти на светодиод ( на весь массив 380*3=1140 байт), если можно хранить побитово 0/1 - 0x0/defaultColor, что на весь массив займет 48 байт?
Даже если хранить не цвет а число 0/1, как изначально в массиве byte digits[][], то у вас произойдет неплохая оптимизация кода - массив займет 380 байт и чтобы записать цифру из digits[][] в leds[] вам нужно будет всего лишь скопировать 63 байта с одного адреса в памяти по другому простым циклом или с помощью memcpy(). И линейный цикл копирования большинство компиляторов заменит на вызов memcpy().

for(int i=0; i < 63; ++i) 
   leds[beginPosition + i] = digits[number][i];

// большинство компиляторов заменит на
memcpy( &leds[beginPosition], &digits[number][0], 63);

Если заменить хранение абсолютного значения цвета на признак, то уже должно хватить памяти - leds[] 380 байт + digits[][] 630 байт + макросы = 1 Кб, т.е. половина от имеющейся.

Проверьте, сколько памяти у вас занимает тип int - 2 или 4 байта? Скорее всего 2 байта - обычно это можно изменить в настройках компилятора.

Проверьте (на всякий случай) какое выравнивание данных установлено в компиляторе - установите в 1 байт.

Макросы #define LED_PIN 12 по-умолчанию будут транслироваться в целые и занимать 2 байта. Замените на const byte LED_PIN = 12; - будет занимать 1 байт.

Я не сталкивался с программированием Arduino, поэтому это - общие рекомендации по уменьшению расхода памяти.