Увеличение памяти ардуино уно
Столкнулся с проблемой нехватки flash-памяти - не хватает места для хранения скетча. Оптимизировал код как можно, а надо еще много всего добавить.
Есть ли внешнии модули, которые увеличивают flash-память? Или можно как-нибудь увеличить место для хранения скетча?
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Замена микроконтроллера вам нужна, если действительно оптимизировали.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
кстати ,вопрос к тем кто сюда заглянет : можно ли в среде ардуино настроить PROGMEM на работу с внешней энергонезаисимой памятью,по шине I2C или SPI?или как то по другому нативно расширить адресное пространство(не RAM,о примере ардуино на 512КБ ,знаком)
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Progmem наврядли можно прям вот так с полтычка, иначе давно бы уже все еепромы по i2c в полный рост пользовали. А вот какой-нить драйвер можно, наверное, накатать. Только медленный он будет. Или с доп. буфером, как для SD-карты мутить.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
EEPROM использовать вообще не проблема. А вот если скетч не влазит - оптимизация, или замена контроллера.
Вообще чистый СИ очень сильно снижает вес программы. Но, как сказал mixail844 , нужно определиться что там у вас за код, и что в нем используется. То что можно подгрузить - на флешку, а код перевести (хотя бы частично) в чистый СИ.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
zzzzza , и RAM и PROGMEM находятся внутри адресного пространства процессора, а I2C или SPI - нет. Защищенного режима у AVR подобно как в 386+ тоже нет, значит программно прозрачная эмуляция тоже невозможна. Т.е. хранить константы где-то снаружи по I2C или SPI можно (написав для их добывания свои функции), а исполнять код из них - нет.
Могу порекомендовать Мегу 2560 - у нее и flash памяти побольше и при необходимости можно организовать внешнюю память в общем адресном пространстве.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Либо переходить на STM или ESP - вот там пямяти на много больше.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Спасибо за ответы!
Очень много места занимает все то, что связано с дисплеем. Как подключаешь эту библиотеку, сразу минус 30-40 процентов памяти. И каждый вызов дисплейных функцей тоже немало места занимает. Как смог все вынес в функции, чтобы лишний раз их не вызывать.
Думал о меге, но у нее размер большой. Сейчас думаю между STM и Iskra JS. Больше в пользу Iskra JS, так как побаиваюсь, что памяти STM тоже может не хватить в будущем. Но придется переписывать все на JavaScript. Отсюда вопрос для тех кто сталкивался с микроконтроллерами с AVR процессорами, на которых установлен интерпретатор JavaScript: можно ли как-то писать код на Arduino Wiring?
Возможно, можно снести интерпретатор, но тогда придется писать на чистом СИ, а это, как я думаю, придется переписывать библиотеки, да и явно море проблем будет.
Микроконтроллер ATmega328P на базе которого работают платы Arduino Nano и Arduino UNO обладает достаточно скромными характеристиками необходимой для реализации сложных проектов в плане оперативной (энергозависимой) памяти SRAM.
Можно поискать альтернативу на других мощных платформах, взять какой-нибудь 32-х битный STM - но цена вопроса будет уже другая ну и совсем не факт, что на другой платформе будут работать библиотеки предназначенные для Arduino. В каких ситуациях может не хватать оперативной памяти? - В первую очередь при работе с графическими дисплеями. Разберем пример:
У нас есть вот такой монохромный дисплей с разрешением 128х64.
Для работы с ним в оперативной памяти потребуется выделить буфер ( однобайтовый массив) размерностью
128х64/8 = 1024 байта
т.е. мы займем половину памяти Arduino - и в принципе Arduino с такой задачкой справится. А, что если взять вот такой дисплей, да еще и поработать с оттенками серого (4 цвета).
Нам уже потребуется
400х300/4 = 30000 байт оперативной памяти.
Разумеется, что такой объем данных не влезет в оперативную память
Arduino да и многих других Arduino подобных платформ.
Можно поискать подходящую платформу - а можно прикрутить внешнюю SRAM память. Для решения задачи я выбрал микросхему 23LC512 c интерфейсом SPI от производителя Microchip
Объем памяти 512K bit / 8 = 64кб
После подключения, мы получаем дополнительные 65535 однобайтовых ячеек где можем хранить наши переменные. Память это энергозависимая то есть данные хранятся только пока у нас есть питание - за то мы не ограничены в количестве циклов записи/чтения. Работать с этой памятью не намного сложнее чем с обычным массивом - я даже не буду использовать библиотеки.
Схема тестового стенда:
Вместо платы Arduino я буду использовать Российскую платформу Iskra Nano Pro на микроконтроллере ATmega328PB. В отличии от оригинальной платы Arduino у нее есть 2-й аппаратный SPI. Работа с памятью будет производится без Ардуиновских библиотек на языке С - но в среде ArduinoIDE. В памяти выделяется область адресов для буфера (куда мы будем подгружать картинки и рисовать графические примитивы) для двух дисплеев, а после создания картинки будем переписывать содержимое памяти на дисплеи через 1-й аппаратный SPI. Такое решение даст минимизацию трудозатрат при редактировании существующих библиотек и позволит работать с дисплеями с высоким разрешением.
Разумеется что можно использовать и оригинальную плату Arduino на микроконтроллере ATmega328P - повесив память на ту же шину, что и дисплеи - но писать код будет несколько сложнее.
Весь код для записи и чтения байтов из внешней SRAM уместился на одной страничке:
Было создано 2 процедуры и 1 функция: Инициализация SPI Запись в память (адрес от 0. 65535, значение 1 байт) Чтение из памяти (адрес от 0. 65535) - возвращает один байт Работу стенда и дополнительные комментарии смотрите в этом видео.
Было создано 2 процедуры и 1 функция: Инициализация SPI Запись в память (адрес от 0. 65535, значение 1 байт) Чтение из памяти (адрес от 0. 65535) - возвращает один байт Работу стенда и дополнительные комментарии смотрите в этом видео.
В данной статье речь пойдет об энергонезависимой памяти EEPROM (электрически стираемое программируемое постоянное запоминающее устройство). Как видно из названия EEPROM является разновидностью ПЗУ , важной особенностью которой является возможность перезаписывать хранимые в памяти значения (в отличие от FLASH-памяти) во время выполнения скетча и сохранять после отключения питания.
Энергонезависимая память EEPROM прекрасно подходит для хранения настроек работы устройства , которые были выбраны пользователем во время его работы и должны быть сохранены при отключении питания. Например, пользователь может задать определенную температуру, при которой микроконтроллер должен включить нагревательный элемент. Или определенную влажность почвы, при которой будет включен автополив. Определенную освещенность, при которой будет включено освещение и т.д. Так же в данной памяти можно логировать данные , получаемые от внешних датчиков и возникающие в процессе работы ошибки для последующей отладки.
В размещенной ниже таблице можно посмотреть сравнение различных типов памяти у микроконтроллеров серии ATtiny и микроконтроллера ATmega328 (основы Arduino UNO).
Как видно из таблицы, размер EEPROM либо равен размеру памяти SRAM (оперативной памяти), либо даже меньше неё. И существенно меньше размера FLASH-памяти (памяти для хранения кода программы).
Работа с памятью EEPROM в среде Arduino UNO отличается от работы с памятью SRAM. При работе с оперативной памятью нам не нужно заботиться, где именно располагается значение переменной, к которой мы обращаемся. Т.к. на этапе компиляции программы под каждую переменную, в зависимости от ее размера, выделяется блок памяти, где и хранится значение переменной. Мы же извлекаем это значение или перезаписываем его, обращаясь к переменной по имени.
При работе с памятью EEPROM мы должны указывать непосредственно адрес байта, в котором храниться переменная . Учитывая, что переменные bool, char, byte – занимают 1 байт, переменные int, word - 2 байта, а переменные long, float – 4 байта.
Т.е. в память EEPROM ATtiny13 можно записать 64 значения переменной типа byte, 32 значения переменной типа int и 16 значений переменной типа long. При этом в качестве адреса ячейки памяти при записи и чтении мы указываем номер первого байта переменной.
Для работы с памятью EEPROM в среде Arduino IDE служит специальная библиотека EEPROM.h . В её примерах есть несколько скетчей, показывающих как работать с основными функциями библиотеки.
Характеристики модуля памяти 24LC512
Из характеристик с сайта производителя видно, что модуль поддерживает питание от 2,5 до 5,5 В, до миллиона циклов записи/удаления и до 200 лет хранения записанных данных.
Далее по тексту я буду приводить выдержки из этого PDF-файла.
Подключение внешней памяти EEPROM к Ардуино
Подключение модуля внешней памяти осуществляется согласно следующей схеме:
Как уже отмечалось выше пины A0, A1 и A2 отвечают за задание адреса чипа, по которому будет обращаться микроконтроллер.
Первые 4 бита постоянные, а значение следующих 3-х как раз и соответствует уровню сигнала на пинах А2, А1 и А0.
Таким образом, соединяя все три пина с землей, получаем адрес 10100000 , что соответствует 0x50 в шестнадцатеричной системе исчисления.
Соединяя пин A0 с питанием, а остальные с землей, получаем адрес 10100001 ( 0x51 ). A1 с питанием, остальные с землей, адрес 10100010 ( 0x52 ). И так далее.
Таким образом, можно последовательно соединить до 8 модулей памяти, у каждого из которых будет свой адрес, по которому к нему будет обращаться микроконтроллер. И при использовании чипа 24LC512 получить в сумме полмегабайта памяти EEPROM!
В частном случае, при подключении только одного модуля памяти EEPROM к микроконтроллеру, будем использовать схему подключения всех контактов A0, A1 и A2 к земле .
Пины, которые отвечают за работу с интерфейсом I2C у различных моделей семейства Ардуино, представлены в таблице расположенной ниже.
Либо можно использовать специальные пины, отмеченные на плате как SDA или SCL. У Arduino UNO это пины, ближайшие к кнопке RESET.
Пины передачи данных SCL и SDA должны быть соединены подтягивающим резистором на 10 кОм с питанием.
Основные функции библиотеки EEPROM.h.
EEPROM.length () - возвращает размер памяти EEPROM в байтах.
EEPROM.write (address, value) – записывает значение value величиной 1 байт (0-255) по адресу address (от 0 до EEPROM.length()).
EEPROM.read(address) – читает и возвращает байт данных, размещенной по адресу address.
EEPROM.update(address, value) – обновляет байт памяти (записывает новое значение), если новое значение отличается от текущего. Этот вариант записи значения переменной предпочтительнее, т.к. продлевает срок службы памяти, уменьшая число перезаписей.
EEPROM.put(address, data) – автоматически вычисляет размер и записывает данные любого типа по адресу address .
С помощью данной функции можно размещать в памяти переменные разных размеров.
Например, можно последовательно записывать в память переменные разной длины:
не забывая вычислять размер переменной в байтах и сдвигать начальный байт записи на данный размер:
Так же можно объединить значения переменных в массив или сами переменные в структуры и записывать с помощью функции EEPROM.put() массив или структуру целиком.
EEPROM.get(address, data) – считывает данные по адресу address и заносит их в указанную переменную data .
Естественно, что тип и размер данных, записанных с помощью функции EEPROM.put(), должен совпадать с типом и размером данных, читаемых функцией EEPROM.get(). В примерах библиотеки есть скетчи, иллюстрирующие работу этих функций.
Еще в библиотеке есть оператор EEPROM[] , который позволяет работать с памятью EEPROM как с массивом байтов.
В следующей статье, я расскажу, как увеличить объем памяти EEPROM до 64 КБ . Это будет особенно актуально для микроконтроллеров с малым объемом всех типов памяти, таких как ATtiny .
За счет того, что скорость чтения данных из памяти EEPROM очень велика, мы можем использовать внешнюю память EEPROM как дополнительную оперативную память, либо хранить в ней достаточно объемные массивы данных. Например, шрифты для работы с LED-матицами и LCD-дисплеями. В статье " Создание анимации для LED матрицы 16x16 адресных светодиодов ", мы хранили массив изображения с помощью ключевого слова PROGMEM во FLASH-памяти (из-за нехватки оперативной памяти). Подключив внешнюю EEPROM память, изображения и шрифты можно будет хранить во внешней памяти , оставив FLASH-память исключительно для того, для чего она и предназначена, т.е. для хранения прошивки микроконтроллера.
Спасибо, что дочитали до конца! Если статья понравилась, нажмите, пожалуйста, соответствующую кнопку. Если интересна тематика электроники и различных электронных самоделок, подписывайтесь на канал. До встречи в новых статьях!
Подобный модуль будет полезен, когда не хватает встроенной EEPROM памяти микроконтроллера. Либо она вовсе отсутствует (как у многих микроконтроллеров семейства PIC, о которых мы поговорим в дальнейших статьях). Внешнюю память большого объема, такую как 24LC512, можно использовать в качестве замены SD-карты. Когда подключение кардридера к микроконтроллеру не целесообразно (или не возможно, вследствие его характеристик).
Например, можно хранить достаточно большую статистику от различных датчиков и ее основе выбирать оптимальный режим работы устройства. Или хранить массивы шрифтов, иконок, картинок для дисплеев и светодиодных матриц.
Чтение и запись данных во внешнюю память EEPROM
Для записи и чтения данных во внешнюю память EEPROM будем использовать интерфейс I2C , который позволяет по двум проводам обмениваться данными с различными датчиками, модулями и устройствами. На схемах линии обозначаются следующим образом: SDA (данные) и SCL (тактовые импульсы) .
Для работы будем использовать библиотеку Wire.h . Она как раз и предназначена для передачи данных, с использованием I2C-интерфейса . Дополнительно устанавливать ее не нужно, она присутствует в стандартных библиотеках Arduino IDE.
Ниже размещен скетч с примером записи данных во внешнюю энергонезависимую память. Ссылка, по которой можно скачать этот скетч, размещена в конце статьи.
Вначале, подключаем библиотеку Wire.h . Далее определяем константу EEPROM_ADDRESS , в которую записываем адрес модуля памяти. Как мы определили выше, в соответствие с нашим подключением, это будет адрес 0x50 . Потом задаем адрес ячейки, в которую будем производить запись. В нашем случае значение может быть от 0 до 65536. И значение переменной (от 0 до 255), которое будет записано по данному адресу.
После этого проводим инициализацию библиотеки Wire.h и Монитора порта.
Теперь переходим к блоку записи данных в память EEPROM.
Начинаем передачу данных, указывая в качестве аргумента функции Wire.beginTransmission(EEPROM_ADDRESS) адрес внешней памяти.
Далее, для записи 1 байта данных, нам фактически нужно передать в подключенный чип памяти 3 байта: 2 из которых будут задавать адрес (номер ячейки), куда будет размещен байт данных, а третий байт – сами данные .
С учетом того, что размер памяти чипа 24LC512 составляет 64 килобайта, т.е. 64 * 1024 = 65536 байт, адрес нужной ячейки памяти можно задать только с помощью 2 байт.
Собственно, эта информация присутствует в сопроводительной документации к модулю памяти:
Собственно мне до лампочки у кого сколько денег и на что они тратятся. У меня и RPI есть и кубик 3 и дуня мега 2560 и мапле для экспериментов. Вот сделал контроллер cnc на нано3, думаю вот не переделать ли на мапле или оранж взять - можно будет сделать на 5-6 движков подключение, а то приходится выдумывать тут всякое извращение.
Да, 128 меги у меня тоже есть, одну даже спаял на плату разработки самодельную
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
1284 сейчас можно взять примерно за 510-530 руб. Согласен, не дешево. Но зато теперь уже родной AVR, а мне например STR32 нужно с 0 осваивать.
Нет ну я понимаю взять atmega128 по 50р, там на теже 128к флэш и "всего" 4к ram
Но брать 1284 по 500 ради +12к ram? В чем счастье?)
Кстати дешевле будет взять atmega128 и прилепить внешние 64 или даже 128к через имеющийся интерфейс ram, работать будет почти как родная память (доступ три такта вместо двух)
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
да, стм это уже другое программирование, кто умеет переходит и не хватает пинов-частоты-прерываний-цапов,а кому нужна очень быстрая разработка, пока хватает ресурсов остаются на арме.
stm32 и есть арм)) имел в виду наверно avr
Не так уж и сложно переходить, даже интересно
у меня правда лень не победима, я для себя делаю библиотеку которая одинаково работает что с avr, что с stm8, чуть позже добавлю stm32. Вот сейчас связал через rs485 atmega с stm8s. На stm8s сразу bmp085, dht22, фоторезистор и термистор. Такая "метео" станция. Сам Мк стоит 16р. И в 8к прошивки еще 1.5к свободны
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
В рамках топика - проблема с нехваткой ОЗУ и более никаких "причин". Всё остальное предлагаю оставить "за кадром", а не мерятся длиной потраченного рубля или какой ещё. :)
Я поднял речь именно в сравнении УНО и пр. "недоМК", урезанных сознательно производителем с целью удешевления в конкретных конструкциях по отношению к "полному набору" Мега2560. Что ежели вам не хватает ОЗУ, то вполне можно взять модель постарше и/или воспользоваться x-bus шиной дабы прикрутить "сколько надо" к упрощенной модели ..
собственно о том, что линейка Атмела - очень широка и на каждую задачу можно выбрать подходящего зверька .. ан нет, в массовом (судя по постам тут) любительском применении настырно пользуем одну и туже "чуду-юду", и предпочитаем горестно восклицать "не лезет", "не хаватает", "программно сэмулировать - медленно" .. нафига это, когда можно взять верного зверька?
Собственно предложения "возьмите STM32 и будет вам щастье" .. как ни странно из той же самой оперы .. нежелания ВЫБИРАТЬ конкретного зверька под конкретные нужды .. там тоже ведь "свой зоопарк" не так ли? :)
По нехватке ОЗУ у Атмела: да, моя практика показала что размер встроенного ОЗУ сильно коррелирует с объемом тех задач управления, на которые и был рассчитан этот конкретный зверек. Что для Меги, что для УНЫ но .. памяти хватает на 90% задач.
/* Пробовал делать "слух" на наших микрофонах .. показалось что "вот точно не хватит" .. 8килов .. одна оцифровка даже в 10кгц затребует 10килов на 1 сек. записи .. ан нет! Вполне можно оцифровывать сэмплами в буфер 256 байт, иметь 4 буфера оцифровки для выравнивания скоростей и на лету сворачивать сэмпл в упрощенный БПФ в 20-40 байт и искать ключевые части фонем .. так и не доделал, но в целом решение увидел - даже это влезет! */ (вместо спойлера)
Плюс возможность прикрутить к некоторым зверькам внешнее ОЗУ - решает вопрос на 146%. :)
Переход на STM32 и ваще на 32-х разрядную архитектуру требует совсем ИНЫХ причин .. и вот когда они наступают, то да: такая рекомендация полезна. А все эти "дешевле/дороже" - исключительно для нищих.
Распиновка модуля памяти 24LC512
Распиновка модуля памяти 24LC512 выглядит следующим образом:
A0, A1 и A2 – служат для задания адреса модуля, по которому к нему будут обращаться подключенные устройства. Подача высокого уровня сигнала (3,3 – 5 В) на любой из входов соответствует логической единице, низкого уровня сигнала (подключение к земле) – нулю.
WP – защита от записи. При подаче питания на данный вход, запись в память не производится, а только чтение. Для работы режима чтение/запись данный вход должен быть подключен к земле.
SCL и SDA – для обмена данными.
Читайте также: