Совсем недолго играюсь с ардуиной и уже упёрся в потолок по памяти. Вопрос вот в чём. Нельзя ли вынести какие-то редко используемые функции во внешнюю память? 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, выбирает нужный канал и разворачивает его на весь экран еле-еле удалось запихнуть. Неужели единственный способ увеличения объёма памяти - это увеличение количества ардуин?
Храните данные на SD. http://habrahabr.ru/post/115176/ Чтобы освободить память программы, придется оптимизировать код.
Сейчас при компиляции выдаёт: 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 сейчас буду читать-разбираться...
EEPROM мало что даст, раз память программы занимает почти все. Нужно оптимизировать код. Скиньте его сюда, если особых секретов нет, поглядим...
Секретов нет - там вроде всё достаточно просто и комментарии есть. 3 реле (две зоны света на кухне и сауна), 2 кнопки (управление светом на кухне), ИК передатчик (для управления телеком и ресивером) и приёмник (приёмником ловлю сигнал от пульта телека и управляю светом, ну и ещё там по мелочам), пищалка (для отладки). И ко всему этому прикручен веб-сервер =) Я просто хотел сюда повесить ещё и пару датчиков, и дата-логгер на sd, и отправку данных в "народный мониторинг", но похоже, что придётся разносить всё это на разные ардуины и учиться обмениваться информацией между ними...
Для освобождения RAM можно хранить макросы во FLASH. Ключевое слово PROGMEM. А вот с (93%) of program storage space уже надо разбираться. Скорее всего из-за "веб-сервер" вы фактически не угадали с выбором платформы. В linux часть можно что-то перенести?
самая первая задача, которую хотелось решить, это управление сауной через интернет. отсюда и плясал. всё остальное потом "наросло", когда с первой задачей разобрался. и продолжает нарастать =)
Насчет команд для пульта. Первое, что бросается в глаза - во всех командах используются одни и те же числа, меняется только их последовательность. Всего имеем 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 байта). Останется только написать код, который: - в первом случае будет перебирать большой массив, брать из него номера чисел для маленького массива и уже из маленького массива вытаскивать искомое число - во втором случае будет перебирать большой массив, брать из него очередной байт, пилить его пополам и каждую половинку использовать как номер числа из маленького массива. Если непонятно написал, спрашивайте, постараюсь внести ясность
Код для обработки по первому варианту: Код (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]; // второе число } }