В настоящее время мой эскиз проверяет входной контакт каждый раз вокруг основного цикла. Если он обнаруживает изменение, он вызывает пользовательскую функцию, чтобы ответить на него. Вот код (урезанный до самого необходимого):
int pinValue = LOW;
void pinChanged()
{
//...
}
void setup()
{
pinMode(2, INPUT);
}
void loop()
{
// Read current input
int newValue = digitalRead(2);
// Has the input changed?
if (newValue != pinValue) {
pinValue = newValue;
pinChanged();
}
}
К сожалению, это не всегда работает должным образом для очень коротких изменений на входе (например, коротких импульсов), особенно если loop()
работает немного медленно.
Есть ли способ заставить Arduino обнаруживать изменение входа и автоматически вызывать мою функцию?
Ответы:
Вы можете сделать это с помощью внешних прерываний. Большинство Arduinos поддерживают это только на ограниченном числе контактов. Для получения полной информации см. Документацию по
attachInterrupt()
.Предполагая, что вы используете Uno, вы можете сделать это так:
Он будет вызываться
pinChanged()
всякий раз, когда обнаруживается изменение на внешнем прерывании 0. На Uno, который соответствует выводу GPIO 2. На других платах нумерация внешних прерываний отличается на других платах, поэтому важно проверить соответствующую документацию.Однако у этого подхода есть ограничения. Пользовательская
pinChanged()
функция используется в качестве подпрограммы обработки прерывания (ISR). Это означает, что остальная часть кода (все внутриloop()
) временно останавливается во время выполнения вызова. Чтобы предотвратить нарушение важного времени, вы должны стремиться сделать ISR максимально быстрыми.Также важно отметить, что никакие другие прерывания не будут выполняться во время вашего ISR. Это означает, что все, что зависит от прерываний (например, ядро
delay()
иmillis()
функции), может не работать должным образом внутри него.Наконец, если вашему ISR необходимо изменить какие-либо глобальные переменные в эскизе, они обычно должны быть объявлены как
volatile
, например:Это важно, потому что он сообщает компилятору, что значение может неожиданно измениться, поэтому следует соблюдать осторожность, чтобы не использовать его устаревшие копии / кэши.
источник
pinChanged()
должно быть как можно короче. Следовательно, обычно минимальное время должно быть временем выполнения самойpinChanged()
функции.volatile
, если глобальная переменная шире, чем 1 байт, как, например, someNumber, необходимо защитить от прерывания смены штырьков, возникающего между доступами байтов программой. Такое утверждениеsomeNumber +=5;
включает в себя добавление младших байтов и добавление старших байтов с включенным переносом. Эти два (больше, для более широких переменных) не должны быть разделены прерыванием. Достаточно отключить прерывания и восстановить их до и после операции (соответственно).Любое состояние изменения на любом выводе, настроенном как цифровой вход, может создать прерывание. В отличие от уникальных векторов для прерываний, вызванных INT1 или INT2, функция PinChangeInt использует общий вектор, а затем подпрограмма обработки прерываний (также известная как ISR) для этого вектора должна затем определить, какой контакт изменился.
К счастью, библиотека PinChangeInt делает это легко.
источник
Если вы хотите обнаружить напряжение , превышающее пороговое значение , а не просто ВЫСОКОЕ или НИЗКОЕ, вы можете использовать аналоговый компаратор. Пример скетча:
Это может быть полезно для таких вещей, как детекторы света, где вам может потребоваться обнаружить изменение (скажем) от 1 В до 2 В на входе.
Пример схемы:
Вы также можете использовать Input Capture Unit на процессоре, который запоминает точное время определенных входов, сохраняя текущий счетчик Timer / Counter 1. Это позволяет вам сохранить точный (ну, почти точный) момент, когда событие возник интерес, вместо того, чтобы вводить задержку (вероятно, несколько микросекунд), прежде чем ISR можно будет использовать для захвата текущего времени.
Для приложений, критичных по времени, это может повысить точность.
Пример применения: превратите Arduino в тестер конденсаторов
источник