Самопрограммирование Ардуино

Я заметил, что некоторые чипы Atmel могут выполнять «самопрограммирование», и я занимаюсь проектом для любителей, в котором мне нужно изменить «настройки» моего Arduino без повторной загрузки кода через Arduino IDE.

Можно ли это сделать? Если это возможно. Пожалуйста, расскажите мне немного о том, как это сделать.

Заранее спасибо!

, 👍1


6 ответов


Лучший ответ:

6

В Arduino есть две области энергонезависимой памяти: Flash и EEPROM.

Flash — это место, где хранятся ваша программа и константы. Переменные со значениями по умолчанию также сохраняют значения по умолчанию во Flash.

EEPROM – это гораздо меньшая по размеру область, не имеющая определенного назначения. Вы можете хранить там любые значения.

Флэш-память может записываться только с помощью кода, находящегося в области загрузчика флэш-памяти. Это важно. Программа не может изменять себя. Только загрузчик может модифицировать программу – и то только частями («страницами»). Ему приходится стереть целую страницу, прежде чем он сможет записать на нее данные.

Причина, по которой вы не можете изменять Flash из основной программы, проста: Flash — единственное место, из которого может выполняться код. Если вы сотрете страницу флэш-памяти, содержащую код, программирующий флэш-память, все умрет. Ужасно. Таким образом, это остановилось, прежде всего, не позволив этому случиться.

EEPROM, наоборот, может быть записан чем угодно — загрузчиком или основной программой. Кроме того, отдельные значения можно изменять по своему желанию – не нужно стирать страницы.1

Итак, чтобы ответить на вопрос, стоящий за вашим вопросом («Как я могу хранить и изменять настройки?»): это довольно просто — храните их в EEPROM.

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


1: В некоторых системах нет EEPROM, поэтому они эмулируют его с помощью Flash. Этим системам по-прежнему приходится стирать Flash на страницах, но они стараются делать это прозрачно. Некоторые (например, ESP8266) используют метод commit() для обновления пакета значений. Другие, например платы ChipKIT, используют выравнивание износа и раздельную индексацию записи, чтобы уменьшить необходимость стирания страниц.

,

2

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

Другой (возможно, более простой) вариант — установить внешнюю микросхему EEPROM в разъем для хранения настроек, чтобы вы могли программировать ее отдельно от модуля. Таким образом, вам не понадобится меню в вашем проекте.

,

2

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

Вместо этого я бы рекомендовал использовать внутреннюю память EEPROM.

,

3

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

Во-первых, вы можете добавить в свой проект физический интерфейс. Это может быть кнопка и светодиод, клавиатура с ЖК-дисплеем или сенсорный экран.

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

В-третьих, вы также можете использовать Bluetooth вместо последовательного порта.

В-четвертых, вы можете добавить в свой проект Wi-Fi. С помощью Wi-Fi возможно любое решение (веб-страница, приложение для Android...).

Вы также можете комбинировать технологии: иметь минимальный физический интерфейс для экстренных случаев и полноценный интерфейс через Wi-Fi.

С NodeMCU у вас также есть файловая система, в которой вы можете хранить данные приложения. Возможно, его проще использовать, чем EEPROM.

,

3

Да, вы можете самостоятельно запрограммировать их. Для этого можно использовать несколько различных загрузчиков — вот один: https://bitbucket.org/talk2/talk2boot

,

1

Вы можете сделать что-то простое — скажем, иметь 2 контакта для выбора 1 из 4 наборов значений для использования кода. Прочитайте контакты в setup() и соответствующим образом измените значения для использования в цикле().

void setup(){
change = PIND & 0b1100000; // скажем, D7/D6 используются в Uno.
switch (change){
  case 0b00000000:
  // устанавливаем значения для D7/D6 = 00
  break;
  case 0b01000000:
  // устанавливаем значения 01
  break;
  case 0b10000000:
  // устанавливаем значения 10
  break;
  case 0b11000000:
  // устанавливаем значения 11
  break;
  }
}

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

,