Проблема с большим трёхмерным массивом

Тема в разделе "Arduino & Shields", создана пользователем Mihej, 12 фев 2014.

  1. Mihej

    Mihej Нерд

    Всем привет! Создаю статичный трёхмерный массив в Arduino IDE:
    Код (Text):
    byte angel[28][3][80]  = { /*здесь куча цифр*/};
    . Для проверки работоспособности кидаю числа из массива в Serial-порт, а там пусто. Беру массив поменьше размером:
    Код (Text):
    byte a[3][2][3]={/*заполняем числами*/}
    . Во втором массиве, все числа прекрасно выводятся в порт. Числа в массивах из диапазона (0-180). Размер загруженного счетча около 10кб. Заливаю в Arduino UNO. Не могу поверить что проблема из-за больших размеров первого массива.

    Мне очень нужен первый массив, в чём проблема, почему он не показывает свои значения? Может кто в курсе?
     
  2. Megakoteyka

    Megakoteyka Оракул Модератор

    А покажите код на всякий случай.
     
  3. Unixon

    Unixon Оракул Модератор

    Mihej, а вы не забыли, что у ATmega328 всего 2Кб оперативной памяти (SRAM)? Вы пытаетесь в ней разместить массив размером в 28*3*30=6720=6.5625Кб т.е. более, чем в три раза, больше доступной памяти.
     
    Mihej нравится это.
  4. Megakoteyka

    Megakoteyka Оракул Модератор

    Пихайте массив в программную память. См. PROGMEM.
    Unixon, а почему компилятор это проглотил? Это же статический массив, вроде должен был ругнуться... или нет?
     
    Последнее редактирование: 13 фев 2014
    Mihej нравится это.
  5. Mihej

    Mihej Нерд

    Вот мой код:
    Код (Text):
    byte a[3][2][3]={
                    {
                        {1,2,3},
                        {3,2,1},
                    },
                    {
                        {4,5,6},
                        {6,5,4},
                    },
                    {
                        {7,8,9},
                        {9,8,7},
                    }
                };
    byte angel[28][3][80]  = {
                                                      //Этот массив огромный, писать не буду
                                              };
    void setup()
    {
      Serial.begin(9600);
    }
    void loop()
    {
      Serial.println(angel[0][0][0]); //Пытаемся отправить любое число из массива
      delay(500);
    }
     
  6. Mihej

    Mihej Нерд

    То есть получаеться, что мне лучше разбить исходный массив на 28 двумерных массивов, а потом сделать массив указателей на двумерные массивы? Тогда в оперативку будет подгружаться только определённый двумерный массив?
     
  7. Mihej

    Mihej Нерд

    А не, не то, понял. Копаю PROGMEM...
     
  8. NR55RU

    NR55RU Гик

    Дело в том что компилятор при объявлении переменной выделает под нее память, даже если вы там ничего не вводите.
    Это примерно как склад скажем на 100м/куб .... вы отправляете заявку (объявляете переменную) на то что вам нужно место под 25 м/куб которые вы ВОЗМОЖНО туда сложите, то есть склад резервируется, но это не значит что вы реально привезете туда груз и заполните.
    Таким образом размер склада для других уже будет лишь 75 м/куб так как 25 вы зарезервировали. Хотя по факту место пустует но заведующий склада считает это место занятым и не важно есть там груз или нет :)
    Таким образом объявляя массив вы пытаетесь зарезервировать места больше чем может вам быть предоставлено.
     
    Mihej нравится это.
  9. Mihej

    Mihej Нерд

    Вроде заработало во так:
    Код (Text):
    #define __PROG_TYPES_COMPAT__
    #include <avr/pgmspace.h>

    prog_uchar angel[28][3][80] PROGMEM = {/*Куча цифр*/};

    void setup()
    {
      Serial.begin(9600);
    }

    void loop()
    {
     
      Serial.println(prog_int16_t(angel[1][0][0])); //Кидаем какое нибудь число из массива
      delay(500);
    }
    Всем большое спасибо за ответы, если бы не PROGMEM - тупил бы я ещё долго:D
     
  10. Megakoteyka

    Megakoteyka Оракул Модератор

    А программно посчитать значения элементов массива, кстати, нельзя? Или там "случайный" набор данных?
     
  11. Mihej

    Mihej Нерд

    В том то и дело, что там набор углов поворота 3-х сервоприводов, которые задают движение механической руки (вперёд, вверх), так чтобы клешня всегда была параллельно поверхности стола.
     
  12. Mihej

    Mihej Нерд

    Блин, теперь такой бред, делаю в цикле:
    Код (Text):
    for(int i=0; i< 80; i++)
      {
      Serial.println(prog_int16_t(angel[0][0][i]));
      delay(100);
    }
    В порт выдаются левые числа, а если явно задаю, то всё нормально:
    Код (Text):
    Serial.println(prog_int16_t(angel[0][0][2]));
    В чём проблема?
     
  13. Megakoteyka

    Megakoteyka Оракул Модератор

    pgm_read_... сделать не забыли? Просто так обращаться в память программ нельзя, нужно прочитать оттуда данные при помощи соответствующей (конкретному типу данных) функции. Тогда в памяти программ будет храниться большой массив, а при необходимости его использовать каждый его элемент должен быть сперва прочитан в переменную, находящуюся в памяти данных. И вот ее уже можно использовать.
    http://arduino.cc/en/Reference/PROGMEM

    А еще можно рассмотреть вариант подключения SD-карты и хранения данных на ней.
    Или внешней EEPROM.
     
    Последнее редактирование: 13 фев 2014
    Mihej нравится это.
  14. Mihej

    Mihej Нерд

    Megakoteyka, точно спасибо, по-пойзже попробую и отпишусь)
     
  15. Mihej

    Mihej Нерд

    Ура! Вроде работает теперь:
    Код (Text):
    #define __PROG_TYPES_COMPAT__
    #include <avr/pgmspace.h>

    prog_uchar angel[28][3][80] PROGMEM = {/*Куча цифр*/};

    void setup()
    {
      Serial.begin(9600);
    }

    void loop()
    {
    for(int i=0; i< 80; i++)
      {
    Serial.println(pgm_read_byte(&angel[0][0][i])); //Кидаем числа из массива в цикле
      delay(500);
      }
    }
     
    Megakoteyka нравится это.