Скетч слишком большой

Тема в разделе "Arduino & Shields", создана пользователем swell{d}, 4 фев 2014.

  1. swell{d}

    swell{d} Нерд

    Совсем недолго играюсь с ардуиной и уже упёрся в потолок по памяти.
    Вопрос вот в чём. Нельзя ли вынести какие-то редко используемые функции во внешнюю память? SD, например? Чтобы при необходимости ардуина обращалась к какому-то файлу, выполняла "инструкции" и закрывала его? У меня Arduino Yun, если что.

    Делаю "макросы" для управления телевизором (самсунг). Чтобы закодить одну кнопку пульта, приходится использовать конструкции типа:

    unsigned int S_pwr[68] = {4600, 4350, 700, 1550, 650, 1550, 650, 1600, 650, 450, 650, 450, 650, 450, 650, 450, 700, 400, 700, 1550, 650, 1550, 650, 1600, 650, 450, 650, 450, 650, 450, 700, 450, 650, 450, 650, 450, 650, 1550, 700, 450, 650, 450, 650, 450, 650, 450, 650, 450, 700, 400, 650, 1600, 650, 450, 650, 1550, 650, 1600, 650, 1550, 650, 1550, 700, 1550, 650, 1550, 650};
    irsend.sendRaw(S_pwr, 68, 38);

    Даже простенький макрос, который включает телевизор, запускает смарт-хаб, открывает приложение для iptv, выбирает нужный канал и разворачивает его на весь экран еле-еле удалось запихнуть.
    Неужели единственный способ увеличения объёма памяти - это увеличение количества ардуин?
     
  2. CryNET

    CryNET Гик

    Внешние EEPROM и Flash, можно и SD-Card думаю
     
  3. Корней

    Корней Гик

    Скетч, то есть код, большой или количество данных в ОЗУ (RAM) не помещается?
     
  4. Megakoteyka

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

    Храните данные на SD.
    http://habrahabr.ru/post/115176/

    Чтобы освободить память программы, придется оптимизировать код.
     
  5. swell{d}

    swell{d} Нерд

    Сейчас при компиляции выдаёт:
    Sketch uses 26 666 bytes (93%) of program storage space. Maximum is 28 672 bytes.
    Global variables use 2 025 bytes (79%) of dynamic memory, leaving 535 bytes for local variables. Maximum is 2 560 bytes. Low memory available, stability problems may occur

    И действительно - программа выполняет только один проход по loop и зависает. При сокращении числа строк - работает норм.

    Про внешние eeprom сейчас буду читать-разбираться...
     
  6. Megakoteyka

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

    EEPROM мало что даст, раз память программы занимает почти все. Нужно оптимизировать код. Скиньте его сюда, если особых секретов нет, поглядим...
     
  7. swell{d}

    swell{d} Нерд

    Секретов нет - там вроде всё достаточно просто и комментарии есть.
    3 реле (две зоны света на кухне и сауна), 2 кнопки (управление светом на кухне), ИК передатчик (для управления телеком и ресивером) и приёмник (приёмником ловлю сигнал от пульта телека и управляю светом, ну и ещё там по мелочам), пищалка (для отладки). И ко всему этому прикручен веб-сервер =)

    Я просто хотел сюда повесить ещё и пару датчиков, и дата-логгер на sd, и отправку данных в "народный мониторинг", но похоже, что придётся разносить всё это на разные ардуины и учиться обмениваться информацией между ними...
     

    Вложения:

    • home_06.zip
      Размер файла:
      2 КБ
      Просмотров:
      463
  8. Корней

    Корней Гик

    Для освобождения RAM можно хранить макросы во FLASH. Ключевое слово PROGMEM.
    А вот с (93%) of program storage space уже надо разбираться. Скорее всего из-за "веб-сервер" вы фактически не угадали с выбором платформы. :)

    В linux часть можно что-то перенести?
     
  9. swell{d}

    swell{d} Нерд

    самая первая задача, которую хотелось решить, это управление сауной через интернет. отсюда и плясал. всё остальное потом "наросло", когда с первой задачей разобрался. и продолжает нарастать =)
     
  10. swell{d}

    swell{d} Нерд

    про linux - не знаю.
     
  11. Megakoteyka

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

    Насчет команд для пульта. Первое, что бросается в глаза - во всех командах используются одни и те же числа, меняется только их последовательность.
    Всего имеем 16 уникальных чисел:
    { 4600, 4350, 700, 1550, 650, 1600, 450, 400, 4550, 4500, 550, 1700, 600, 500, 1750, 1650 }
    Все они хранятся в массивах типа unsigned int, т.е. каждое число занимает по 2 байта памяти.
    Для 6 массивов по 68 значений получим 6 * 68 * 2 = 816 байт памяти.

    Можно хранить один массив из 16 двухбайтных чисел, а в остальных массивах хранить только номера, которые числа имеют в первом массиве. Тогда эти 6 массивов станут занимать в 2 раза меньше места (68 * 6 = 408 байт).
    Но можно пойти еще дальше! Поскольку каждый байт состоит из 8 бит, а в 4х битах можно закодировать числа от 0 до 15 (т.е. 16 штук), мы можем хранить в каждом байте не 1, а сразу 2 номера! Тогда 6 массивов станут занимать вчетверо меньше места в памяти (68 * 6 / 2 = 204 байта).

    Останется только написать код, который:
    - в первом случае будет перебирать большой массив, брать из него номера чисел для маленького массива и уже из маленького массива вытаскивать искомое число
    - во втором случае будет перебирать большой массив, брать из него очередной байт, пилить его пополам и каждую половинку использовать как номер числа из маленького массива.

    Если непонятно написал, спрашивайте, постараюсь внести ясность :)
     
    Последнее редактирование: 4 фев 2014
    Tomasina и swell{d} нравится это.
  12. Megakoteyka

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

    Код для обработки по первому варианту:
    Код (Text):
    // массив уникальных значений
    unsigned int VALUES[16] = { 4600, 4350, 700, 1550, 650, 1600, 450, 400, 4550, 4500, 550, 1700, 600, 500, 1750, 1650 };

    // в старших 4х разрядах элементов этого массива хранятся номера четных элементов,
    // в младших 4х разрядах - номера нечетных
    byte S_PWR[68] = {0, 1, 2, 3, 4, 3, ... };    // команда для пульта

    // функция последовательно извлекает искомые числа
    void sendCommand(byte* cmd)
    {
      for(int i = 0; i < 68; i++)
      {
        unsigned int value = VALUES[cmd[i]];  // искомое число
      }
    }
    Что-то вроде этого должно получиться для второго варианта:
    Код (Text):
    // массив уникальных значений
    unsigned int VALUES[16] = { 4600, 4350, 700, 1550, 650, 1600, 450, 400, 4550, 4500, 550, 1700, 600, 500, 1750, 1650 };

    // в старших 4х разрядах элементов этого массива хранятся номера четных элементов,
    // в младших 4х разрядах - номера нечетных
    byte S_PWR[34] = {0x01, 0x23, 0x43, ... };    // команда для пульта

    // функция последовательно извлекает искомые числа
    void sendCommand(byte* cmd)
    {
      for(int i = 0; i < 34; i++)
      {  
        unsigned int value = VALUES[cmd[i] >> 4];  // первое число
        value = VALUES[cmd[i] & 0xF];              // второе число
      }
    }
     
    Последнее редактирование: 4 фев 2014
    Emilio и swell{d} нравится это.