Режим INPUT #
В данном режиме пин находится в высокоимпедансном состоянии - можно считать, что он подключен к GND последовательно через резистор с сопротивлением в десятки и сотни мегаом - это очень большое сопротивление, практически "обрыв провода", т.е. пин как будто "висит в воздухе". Собственно МК будет измерять напряжение на данном резисторе:
Таким образом, если подключить к нему GND - вольтметр покажет 0, а если подключить VCC - всё это напряжение упадёт на резисторе и МК его измерит. При подключении VCC в цепи пойдёт ничтожно маленький ток (при питании от 5V получится 5 / 100000000
А). Это - измерительная цепь, она практически не потребляет энергию.
Нельзя подавать на пин в режиме входа напряжение выше напряжения питания МК или отрицательное напряжение!
Чтение пина #
Для измерения цифрового сигнала на пине используется функция digitalRead(пин)
(цифровое чтение), где пин
- номер пина по распиновке. Давайте соберём простую схему и измерим сигнал на пине:
void setup() {
Serial.begin(115200);
//pinMode(2, INPUT); // пин по умолчанию как вход, можно не указывать
}
void loop() {
bool signal = digitalRead(2);
Serial.println(signal);
delay(100);
}
В первом случае в порт будет печататься 1
- высокий сигнал, а во втором - 0
- низкий. Аккуратно подключайте провод поочерёдно к 5V
и GND
, не отключая плату от компьютера - значение в мониторе порта будет меняться.
Оставьте провод подключенным к D2
и просто держите его в руках или подключите куда-нибудь в свободное место на макетке (справа от платы). С большой вероятностью в порт пойдут случайные значения 001001100111010100101010
- дело в том, что провод как антенна "ловит" различные наводки из воздуха: окружающего оборудования и сетевых проводов.
Какое напряжение на GPIO МК считает за 0
, а какое за 1
? Это указано в документации на МК, например для Arduino Nano (ATMega328p) за 0
считается напряжение от -0.5 V до 0.3 VCC, а за 1
- от 0.7 VCC до VCC + 0.5, где VCC это напряжение питания. При питании от 5V получится логический ноль при (-0.5.. 1.5)V и единица при (3.5.. 5.5)V
Подтяжка #
Высокоимпедансное состояние удобно тем, что не потребляет энергию. Но у него есть и серьёзный минус - если пин никуда не подключен, то он имеет неопределённое состояние со случайным сигналом. Если в реальном устройстве от такого пина "отвалится" провод - МК начнёт получать с него случайные значения. Страшно представить что случится, если это кнопка - она может "натыкать" в устройстве всё что угодно! Более того, обычно кнопка имеет всего два контакта, то есть может только замыкать и размыкать цепь. Если мы подключим кнопку вот так:
То при нажатии она будет подавать на пин стабильные 5V, их можно будет точно измерить. А вот если отпустить кнопку - пин начнёт получать случайные значения.
У типичной тактовой кнопки контакты соединены следующим образом:
Подключите её и посмотрите что получится. Программа та же, что выше:
При нажатии будет стабильная единица 1
, а при отпускании могут пойти случайные значения. Для решения неопределённого поведения используется подтяжка - в схему добавляется резистор с сопротивлением порядка нескольких десятков кОм, который устанавливает на пине стабильное напряжение, пока кнопка не нажата. Подтяжка делается к противоположному от кнопки полюсу - если резистор подтягивает к VCC - подтяжка называется pull-up, если к GND - pull-down:
Если сопротивление подтяжки слишком маленькое (сотни Ом) - через неё будет идти большой ток, если слишком маленькое (сотни кОм) - могут "пробиться" помехи
Добавьте внешнюю подтяжку в схему двумя способами и понажимайте кнопку, программа та же:
В первом случае нажатая кнопка - это сигнал 1
, а во втором - 0
.
Режим INPUT_PULLUP #
Для удобства подключения кнопок (и не только) МК часто имеют внутреннюю подтяжку в несколько десятков кОм, она активируется через pinMode
. В большинстве МК есть только подтяжка к плюсу питания - INPUT_PULLUP
. В этом режиме никуда не подключенный пин будет выдавать стабильный высокий сигнал. Давайте добавим этот режим на тот же пин и подключим кнопку без внешних резисторов:
void setup() {
Serial.begin(115200);
pinMode(2, INPUT_PULLUP);
}
void loop() {
bool signal = digitalRead(2);
Serial.println(signal);
delay(100);
}
Теперь кнопка может стабильно опрашиваться без внешних резисторов, выдавая 0
при нажатии и 1
при отпускании.
Пин, к которому подключен светодиод на плате (13 на Arduino Nano/UNO) некорректно работает в режиме INPUT_PULLUP
- имеет сигнал LOW
, так как подключенный светодиод тянет его к GND через свой резистор!