Как очистить память ардуино uno

Обновлено: 06.07.2024

Согласно документации Arduino, ATmega328 имеет 32 КБ флэш-памяти для загрузчика + загруженный эскиз и только 2 КБ SRAM для данных времени выполнения. ATmega2560 имеет немного больше, общий объем 256 КБ и 8 КБ соответственно.

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

Что вы можете сделать, если у вас кончились? Например, если ваш эскиз слишком большой или вам нужно обрабатывать много данных (например, строк) во время выполнения? Есть ли способ расширить Flash или SRAM?

Попробуйте использовать некоторые переменные оптимизации. Некоторые различные переменные обсуждаются здесь Используйте надлежащие области действия для ваших переменных, если это еще не сделано, компилятор оптимизирует использование оперативной памяти для вас, когда переменные не используются. Вы можете использовать Teensy 3.2 (с программным обеспечением Teensyduino), которое будет сравнимо с Arduino. Учитывая, что у вас заканчивается RAM / PROGMEM, это также означает, что вы, скорее всего, пытаетесь подтолкнуть Arduino. Teensy 3.2 не намного дороже. но имеет: 32-битную, 72 МГц (wtf !?) флэш-память 256 КБ, 64 КБ ОЗУ и 3x UART. Не больше памяти программ, как у ATmega2560, но должно быть достаточно оперативной памяти и увеличения скорости.

Оптимизация
Низкоуровневое программирование для встроенных систем весьма отличается от программирования для устройств общего назначения, таких как компьютеры и мобильные телефоны. Эффективность (с точки зрения скорости и пространства) гораздо важнее, потому что ресурсы стоят на первом месте. Это означает, что самое первое, что нужно сделать, если вам не хватает места, это посмотреть, какие части вашего кода вы можете оптимизировать.

С точки зрения сокращения использования программного пространства (Flash) размер кода может быть довольно трудно оптимизировать, если вы неопытны или более привыкли к программированию для настольных компьютеров, которые не склонны к этим навыкам. К сожалению, не существует подхода «волшебной пули», который будет работать во всех ситуациях, хотя он помогает, если вы серьезно задумаетесь над тем, что в действительности должен иметь ваш эскиз . Если функция не нужна, уберите ее.

Иногда также полезно определить, где несколько частей вашего кода одинаковы (или очень похожи). Вы можете сжать их в многократно используемые функции, которые можно вызывать из нескольких мест. Однако имейте в виду, что иногда попытка сделать код слишком многократно используемым на самом деле делает его более многословным. Это сложный баланс для забастовки, который имеет тенденцию приходить с практикой. Можно потратить некоторое время на изучение того, как изменения кода влияют на вывод компилятора.

Оптимизация данных времени выполнения (SRAM) имеет тенденцию быть немного легче, когда вы к этому привыкли. Очень распространенная ловушка для начинающих программистов - использование слишком большого количества глобальных данных. Все, что объявлено в глобальном масштабе, будет существовать в течение всего времени существования эскиза, и это не всегда необходимо. Если переменная используется только внутри одной функции, и она не должна сохраняться между вызовами, то сделайте ее локальной переменной. Если значение должно быть разделено между функциями, подумайте, можете ли вы передать его как параметр вместо того, чтобы делать его глобальным. Таким образом, вы будете использовать SRAM только для тех переменных, которые вам действительно нужны.

Еще одним убийцей использования SRAM является обработка текста (например, использование String класса). Вообще говоря, вам следует избегать выполнения операций со строками, если это возможно. Они огромные боровы памяти. Например, если вы выводите много текста в последовательный порт, используйте несколько вызовов Serial.print() вместо вместо конкатенации строк. Также попытайтесь сократить количество строковых литералов в вашем коде, если это возможно.

Избегайте рекурсии, если это возможно. Каждый раз, когда выполняется рекурсивный вызов, стек поднимается на уровень глубже. Перефразируйте ваши рекурсивные функции, чтобы они стали итеративными.

Использование EEPROM
EEPROM используется для долговременного хранения вещей, которые изменяются только изредка. Если вам нужно использовать большие списки или справочные таблицы с фиксированными данными, подумайте о том, чтобы заранее сохранить их в EEPROM и извлекать только то, что вам нужно, когда это необходимо.

Очевидно, что EEPROM довольно ограничен по размеру и скорости и имеет ограниченное количество циклов записи. Это не лучшее решение для ограничения данных, но этого может быть достаточно, чтобы облегчить нагрузку на Flash или SRAM. Также возможно взаимодействие с аналогичным внешним хранилищем, таким как SD-карта.

Расширение
Если вы исчерпали все остальные варианты, возможно, расширение возможно. К сожалению, расширение флэш-памяти для увеличения места в программе невозможно. Тем не менее, есть возможность расширить SRAM. Это означает, что вы сможете реорганизовать свой эскиз, чтобы уменьшить размер кода за счет увеличения размера данных.

Получить больше SRAM на самом деле довольно просто. Один из вариантов - использовать один или несколько чипов 23K256 . Доступ к ним осуществляется через SPI, и есть библиотека SpiRAM, которая поможет вам их использовать. Просто знайте, что они работают при 3,3 В, а не 5 В!

Если вы используете Mega, вы также можете получить щиты расширения SRAM от Lagrangian Point или Rugged Circuits .

Я просто учитель Arduino с моим сыном, и я был удивлен, что, когда я снова подключил USB-кабель к Arduino, программа все еще работала, и я подумал про себя: «Хорошо, что я не сделал просто взорвите что-нибудь ».

Итак, как обычно люди называют это днем ​​с этими вещами? Обычно вы загружаете голые кости, ничего не нарисовывая или просто отключая все?

При загрузке Arduino запустит любую последнюю программу. Решение: не включайте его, если вы не хотите его запускать.

Когда из коробки, Arduino обычно запускает программу Blink. Поэтому вы можете просто загрузить это и называть его днем, если вы хотите «перезагрузить» его.

Или иметь программу цикла с командой sleep.

Если вы столкнулись с загрузчиком USB через контакты icsp, этого недостаточно, вам придется переустановить загрузчик. Но если вы загружаете программы через usb или напрямую с помощью программиста, нет проблем с загрузкой Blink или другой фиктивной программы для ее сброса.

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

  • Загрузите минимальный минимальный эскиз, найденный в Файл -> Примеры -> Базовый в arduino -ide
  • Загрузите эскиз с большой задержкой в ​​цикле.
  • Загрузите эскиз с помощью вызова exit() из setup() ( Спасибо @Peter! )

* Стоп - просто образный. Плата не перестает работать.

Самое главное, что может пойти не так, если вы отложите Arduino на пару недель, забудьте, какой эскиз (код) загружен на него, затем вернитесь к нему, подключите оборудование (например, переключатель, Светодиод или двигатель) и неожиданно загораться /включаться, потому что предыдущий код адресовал контакт, к которому он был подключен.

Решение 1. Сначала загрузите новый код.

Простая и безопасная техника заключается в загрузке нового кода, над которым вы работаете сегодня до . Вы подключаете любое оборудование. Теперь вы знаете, что делает код, какие контакты он использует, а затем затем подключите оборудование (желательно сначала отключить Arduino, отключив его).

Затем, когда вы снова подключаете питание, он запускает эскиз, который вы загрузили, вы подключили свое оборудование, и все должно быть хорошо.

Решение 2. Загрузите эскиз «ничего не делать».

Вы можете загрузить этот короткий эскиз:

Он ничего не делает. Все контакты останутся в виде входов, поэтому вы можете безопасно присоединить свое оборудование, а затем начать кодирование своего нового проекта.

Безопасность в первую очередь

Хорошим правилом является не подключать и не отключать оборудование (например, светодиоды, переключатели, двигатели) с поданной мощностью. Если вы отвлекаетесь и подключаетесь к неправильному гнезду на плате, вы можете немедленно повредить либо то, что вы подключены, либо Arduino, либо и то, и другое.

При выключенном питании вы можете в последний момент проверить, что все подключено в нужном месте, правильные полярности и т. д.

Также убедитесь, что у вас нет статического электричества на вашем теле, особенно если вы носите перемычку или что-то пушистое или сидите на ковре.

Лично я всегда добираюсь и прикасаюсь к какой-то металлической части рядом с собой, чтобы дойти до Ардуино. Примером может служить металлический корпус ПК, разъем для наушников или что-то в этом роде.

Если после подключения питания к Arduino (например, с помощью USB-кабеля) вы сразу не видите индикатор питания, немедленно отключите питание! Возможно, вы что-то закрыли, и чем меньше времени вы делаете, тем лучше.

Моя самая большая забота, когда это происходит, я обычно провожу Arduino для моего нового проекта, и я подключаю USB для первоначальной загрузки нового эскиза. Я волнуюсь, не зная, что будет делать предыдущая программа, подключаясь к совершенно другому оборудованию.

До сих пор ничего плохого не произошло, и я не думаю, что буду принимать горящий БЛИНК каждый раз, когда я помещаю один из моих Ардуинов в корзину. Вероятно, это всего лишь вопрос времени.

Если плата arduino подключена к любому другому устройству, отключите все и просто подключите arduino к компьютеру с помощью USB-кабеля и попробуйте загрузить новый эскиз, я надеюсь, что это поможет.

В среде разработки Arduino перейдите к примерам, выберите Eeprom, выберите eeprom clear и затем загрузите эскиз.

Когда светодиод на контакте 13 включится, вы закончите.

NB. Это может занять некоторое время в зависимости от размера EEPROM в Arduino.

Я просто тинкер, изучающий Arduino с моим сыном, и я был удивлен, что, когда я снова подключил USB-кабель к Arduino, программа все еще работала, и я подумал про себя: «Хорошо, что я просто не взорвал ничего вверх «.

Итак, как обычно люди называют это днем ​​с этими вещами? Вы обычно загружаете голыми руками ничего не рисуя или просто отключаете все?

Что вы подразумеваете под «когда я снова подключил USB-кабель к Arduino, программа все еще работала», какое поведение вы наблюдали и какое поведение ожидали? Было ли что-нибудь связано с Arduino? @jippie Да, у меня было подключено несколько светодиодов, и все они загорелись. Почему-то я думал, что программы были загружены в память и будут перезагружены, но так как этого не существует . Программы загружаются во флэш-память, а не в ОЗУ, поэтому они сохраняются даже после отключения питания.

При загрузке Arduino будет запускать любую программу, которая была установлена ​​на нем в последний раз. Решение: не включайте его, если не хотите, чтобы он работал.

Когда Arduino готов к работе, он обычно запускает программу Blink. Таким образом, вы можете просто загрузить это и назвать это день, если вы хотите «сбросить» его.

Или запустите программу цикла с командой сна.

Если вы возились с загрузчиком USB через контакты icsp, этого недостаточно, вам нужно переустановить загрузчик. Но если вы загружали программы через usb или напрямую с помощью программатора, нет проблем с загрузкой Blink или другой фиктивной программы для его сброса.

возможно ли, чтобы он запускал саморазрушающуюся программу без подключения к клеммам напряжения? @PeterTurner, когда нет сил для этого? Нет. Но вы можете добавить программу, которая неправильно использует контакты, и если вы оставите ее на некотором повреждении, можно вызвать (не так много, если контакты не подключены)

Если безопасность является серьезной проблемой, то вы почти всегда должны загружать эскиз с остановкой * на доску, прежде чем называть ее днем. Это было бы хорошей идеей, например, когда ваша доска полупостоянно является частью более крупной системы. Вы можете сделать это:

  • Загрузите набросок Bare Minimum, найденный в File -> Examples -> Basic в arduino-ide
  • Загрузить эскиз с большой задержкой в ​​цикле.
  • Загрузите эскиз с звонком exit() от setup() ( Спасибо @Peter! )

* Стоп просто образный. Доска действительно не перестает работать.

Можете ли вы получить аналогичный (и более постоянный) эффект, позвонив exit() изнутри setup() или loop() ? @ PeterR.Bloomfield Не могу поверить, что я забыл об этом! Зачем беспокоиться о выходе или задержке? Просто имейте void setup () < >void loop () < >- в любом случае внутренне процессор просто зацикливается на том, чтобы «ничего не делать полезного».

Главное, что может пойти не так, если вы отложите Arduino на пару недель, забудете, какой эскиз (код) загружен на него, а затем вернитесь к работе, подключите аппаратное обеспечение (например, переключатель, светодиод или двигатель). ) и он неожиданно загорится / включится, потому что предыдущий код адресован контакту, к которому он подключен.

Решение 1. Сначала загрузите новый код.

Простой и безопасный способ - загрузить новый код, над которым вы работаете сегодня, перед тем, как подключать какое-либо оборудование. Теперь вы знаете, что делает код, какие выводы он использует, а затем подключаете оборудование (предпочтительно поворачивая Arduino. сначала отключи его)

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

Решение 2. Загрузите эскиз «ничего не делать».

Вы можете загрузить этот короткий набросок:

Это "ничего не делает". Все контакты останутся входными данными, так что вы можете безопасно подключить свое оборудование и начать кодировать новый проект.

Безопасность прежде всего

Хорошее правило - не подключать и не отключать аппаратное обеспечение (например, светодиоды, переключатели, двигатели) при включенном питании. Если вы отвлечетесь и подключитесь к неправильной розетке на плате, вы можете немедленно повредить то, что вы подключили, или Arduino, или оба.

Выключив питание, вы можете в последнюю минуту проверить, все ли правильно подключено, правильная полярность и т. Д.

Также убедитесь, что на вашем теле нет статического электричества, особенно если вы носите джемпер или что-то пушистое или сидите на ковре.

Лично я всегда протягиваю руку и прикасаюсь к какой-то металлической части поблизости, чтобы «заземлить» себя, прежде чем дотянуться до Arduino. Примером является металлический корпус ПК, разъем для наушников или что-то в этом роде.

Если после подключения питания к Arduino (например, через USB-кабель) вы не сразу увидите, что загорелся индикатор питания, немедленно отключите питание! Возможно, вы что-то замкнули, и чем меньше времени вы это делаете, тем лучше.

Больше всего меня беспокоит то, что я обычно подключаю Arduino к своему новому проекту и подключаю USB для начальной загрузки нового скетча. Я волнуюсь, понятия не имею, что попытается использовать предыдущая программа, будучи подключенным к совершенно другому оборудованию.

Пока что ничего плохого не произошло, и я не думаю, что буду использовать BLINK каждый раз, когда кладу один из моих Arduinos обратно в мусорное ведро. Это, вероятно, просто вопрос времени.

Если плата Arduino подключена к любому другому устройству, отключите все и просто подключите Arduino к компьютеру с помощью USB-кабеля и попробуйте загрузить новый эскиз, надеюсь, это поможет.

В Arduino IDE перейдите к примерам, выберите Eeprom, выберите eeprom clear и затем загрузите эскиз.

Когда загорится светодиод на контакте 13, все готово.

NB. Это может занять некоторое время в зависимости от размера EEPROM в Arduino.


Тип Чтение из программы Запись из программы Очистка при перезагрузке
Flash Да, PROGMEM Можно, но сложно Нет
SRAM Да Да Да
EEPROM Да Да Нет

EEPROM представляет собой область памяти, состоящую из элементарных ячеек с размером в один байт (как SRAM). Объём EEPROM разный у разных моделей МК:

  • ATmega328 (Arduino UNO, Nano, Pro Mini): 1 кБ
  • ATmega2560 (Arduino Mega): 4 кБ
  • ATtiny85 (Digispark): 512 Б

Важный момент: все ячейки имеют значение по умолчанию (у нового чипа) 255.

Скорость работы с EEPROM (время не зависит от частоты системного клока):

Возможны искажения при записи данных в EEPROM при слишком низком VCC (напряжении питания), настоятельно рекомендуется использовать BOD или вручную мониторить напряжение перед записью.

При использовании внутреннего тактового генератора на 8 МГц, его отклонение не должно быть выше 10% (7.2-8.8 МГц), иначе запись в EEPROM или FLASH скорее всего будет производиться с ошибками. Соответственно все разгоны внутреннего клока недопустимы при записи EEPROM или FLASH.

Библиотека avr/eeprom.h

Запись:

Обновление:

Макросы:

Рассмотрим простой пример, в котором происходит запись и чтение единичных типов данных в разные ячейки:

Точно так же можно хранить массивы:

Ну и напоследок, запись и чтение блока через EEMEM. Адрес придётся преобразовать в (const void*) вручную:

Библиотека EEPROM.h

В отличие от avr/eeprom.h у нас нет отдельных инструментов для работы с конкретными типами данных, отличными от byte, и сделать write/update/read для float/long/int мы не можем. Но зато у нас есть всеядный put/get, который очень удобно использовать! Также можем пользоваться тем, что нам даёт avr/eeprom.h, которая подключается автоматически с EEPROM.h. Рассмотрим пример с чтением/записью байтов:

Логика работы с адресами такая же, как в предыдущем пункте урока! Обратите внимание на работу с EEPROM как с массивом, можно читать, писать, сравнивать, и даже использовать составные операторы, например EEPROM[0] += 10 , но это работает только для элементарных ячеек, байтов. Теперь посмотрим, как работает put/get:

Гораздо удобнее чем write_block и read_block, не правда ли? Put и get сами преобразовывают типы и сами считают размер блока данных, использовать их очень приятно. Они работают как с массивами, так и со структурами.

EEPROM.h + avr/eeprom.h

Ну и конечно же, можно использовать одновременно все преимущества обеих библиотек, например автоматическую адресацию EEMEM и put/get. Рассмотрим на предыдущем примере, вместо ручного задания адресов используем EEMEM, но величину придётся привести к целочисленному типу, сначала взяв от него адрес, т.е. (int)&адрес_еемем

С возможностями библиотек разобрались, перейдём к практике.

Реальный пример

Рассмотрим пример, в котором происходит следующее: две кнопки управляют яркостью светодиода, подключенного к ШИМ пину. Установленная яркость сохраняется в EEPROM, т.е. при перезапуске устройства будет включена яркость, установленная последний раз. Для опроса кнопок используется библиотека GyverButton. Для начала посмотрите на первоначальную программу, где установленная яркость не сохраняется. Программу можно чуть оптимизировать, но это не является целью данного урока.

  • Подключить библиотеку EEPROM.h
  • При запуске: чтение яркости из EEPROM и включение светодиода
  • При клике: запись актуального значения в EEPROM

Полезные трюки

Инициализация

  1. Чтение из EEPROM в переменную
  2. Использование переменной по назначению

Рассмотрим на всё том же примере со светодиодом и кнопками:

Теперь при первом запуске мы получим инициализацию нужных ячеек. Если нужно переинициализировать EEPROM, например в случае добавления новых данных, достаточно изменить наш ключ на любое другое значение в пределах одного байта (0-254). Я пишу именно до 254, потому что 255 является значением ячейки по умолчанию и наш трюк не сработает.

Скорость

Как я писал выше, скорость работы с EEPROM составляет:

При большом желании можно использовать ячейку вместо переменной, т.е. выше мы с вами рассматривали пример, в котором EEPROM читался в переменную в программе, и дальнейшая работа происходила уже с ней. При сильной нехватке оперативной памяти можно читать значение напрямую из EEPROM, ведь это занимает ничтожно мало времени. А вот с записью всё гораздо хуже, там целых 3.3 мс. Например так:

Для изменения значения придётся прочитать ячейку, выполнить нужные операции, и снова в неё записать. Ещё один удобный хак: можно ввести макросы на чтение и запись определённых значений, например:

Получим удобные макросы, с которыми писать код будет чуть быстрее и удобнее, т.е. строка SET_MODE(3) запишет 3 в ячейку 0

Уменьшение износа

Посмотрим на всё том же примере:

    Ёмкий конденсатор по питанию микроконтроллера, позволяющий сохранить работу МК после отключения питания на время, достаточное для записи в EEPROM (

Вариантов уменьшения износа ячеек EEPROM можно придумать много, уникально под свою ситуацию. Есть даже библиотеки готовые, например EEPROMWearLevel. Есть очень интересная статья на Хабре, там рассмотрено ещё несколько хороших алгоритмов и даны ссылки на ещё большее их количество.

Видео

Читайте также: