Как переназначить кнопку сброса Arduino

Можно ли переназначить кнопку сброса для кода, как встроенную кнопку? Мне не нужно его сбрасывать, но было бы полезно запустить его через список циклов светодиодов RGB.

, 👍6

Обсуждение

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


5 ответов


2

Кнопка сброса подключена к контакту сброса Atmega328P-PU. Итак, когда вы нажимаете эту кнопку, контакт сброса получает НИЗКИЙ уровень, который сбрасывает чип!

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

Кстати, да, он нужен для сброса. Когда вы программируете свой Arduino, IDE отправляет команду сброса с вашего ПК через USB для сброса вашего Arduino. Когда Arduino сбрасывается, загрузчик ищет входящий скетч, который предоставляется IDE и т. д....

,

0

Я согласен со всем, что сказал Максимус.

Возможно — вы можете изменить контакт сброса на обычный контакт ввода-вывода.

Для этого вам нужно запрограммировать один из фьюз-битов ATmega328P. Для этого вам понадобится программатор ISP, такой как AVRISPmkII или Atmel ICE. Вам также понадобится такая программа, как Atmel Studio или AVRdude.

Предохранитель отключения сброса является частью предохранителей старшего байта. Сначала вам нужно будет рассчитать высокий предохранитель. Для этого я использую eleccelerator Fusecalc

.

Исходя из моего файла boards.txt, предохранителем верхнего уровня на Arduino Uno по умолчанию является DE. Добавление предохранителя отключения сброса делает его 5E.

Запрограммируйте предохранитель с помощью Atmel Studio или AVRdude с помощью программатора ISP.

Выполните настройки Fusecalc

,

1

Как отмечалось в других ответах, если вы переназначите контакт сброса PC6, запрограммировав предохранитель RSTDISBL, то некоторые из обычных методов загрузки программы во флэш-память станут недоступны. В частности, обычное программирование последовательного порта с использованием Optiboot Arduino зависит от сброса микросхемы по требованию. То же самое можно сказать и о программировании ISP, например, с использованием USBasp или аналогичного устройства.

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

Вот несколько ссылок из таблицы данных Atmel doc8271 для ATmega48A/PA/88A/PA/168A/PA/328/P:

§14.3.2 Альтернативные функции порта C
«Когда RSTDISBL Fuse запрограммирован, этот контакт [PC6] функционирует как обычный контакт ввода-вывода, и часть должна полагаться на сброс при включении питания и сброс при отключении питания в качестве источников сброса. ...”

§28.6 Параметры параллельного программирования, сопоставление контактов и команды
(Описывает проводку и протокол параллельного программирования)

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

Этот метод оставляет все остальные элементы схемы сброса (подтягивающий резистор к 5 В, конденсатор к DTR) на месте, чтобы программирование ISP работало без изменений.

,

9

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

void setup()
{
    // При запуске переходим в следующий режим.
    if (++mode >= NUMBER_OF_MODES) mode = 0;

    // и т. д...
}

Здесь есть небольшая проблема: при запуске программы все глобальные переменные (например, mode выше) должны быть инициализированы Среда выполнения C. Этого можно избежать, используя нестандартную функцию gcc: если вы запрашиваете сохранение переменной в специальном файле .noinit раздел, то он не будет инициализирован. Вот программа, которую я использовал проверить эту идею:

const unsigned int NUMBER_OF_MODES = 5;

__attribute__((section(".noinit"))) unsigned int mode;

void setup()
{
    // При запуске переходим в следующий режим.
    if (++mode >= NUMBER_OF_MODES) mode = 0;

    Serial.begin(9600);
    Serial.print("Current mode: ");
    Serial.println(mode);
}

void loop() {}

Теперь каждый раз, когда я нажимаю кнопку сброса, он переходит в следующий режим среди (0, 1, 2, 3, 4). Основным недостатком по сравнению с использованием обычного ввода является добавленная загрузчиком задержка, которая чуть больше единицы второй.

Несколько слов об инициализации при холодной загрузке: ОЗУ не инициализируется аппаратно и содержит в основном случайные биты. Это значит, что ты не может рассчитывать на то, что mode изначально имеет допустимое значение. Вот почему:

  • Я тестирую ++mode >= NUMBER_OF_MODES, а не ++mode == NUMBER_OF_MODES, так как исходный режим может быть намного больше чем NUMBER_OF_MODES
  • mode — это целое число без знака, иначе мне нужно было бы также проверить это отрицательно.
,

0

Другие ответы у меня не работали (на ATmega168), но я нашел это решение:

const unsigned int NUMBER_OF_MODES = 5;
int * mode;

void setup() {
    mode = (int *) malloc (sizeof (int));

    // При запуске переходим в следующий режим.
    if (++(*mode) >= NUMBER_OF_MODES) (*mode) = 0;


    Serial.begin(9600);
    Serial.print("Current mode: ");
    Serial.println((*mode));
}

вывод:

Current mode: 0
Current mode: 1
Current mode: 2
Current mode: 3
Current mode: 4
Current mode: 0
,