суббота, 3 февраля 2018 г.

Что такое подтягивающий (стягивающий) резистор

Чтобы ответить на этот вопрос давайте посмотрим на следующую схему:
Мы бы хотели отслеживать нажатие кнопки для выполнения каких-то действий. Для этого мы подключили линию +5В через резистор и кнопку к цифровому выводу Ардуино, полагая, что при нажатии на кнопку ток потечет через нее и Ардуино считает на цифровом входе 2 сигнал высокого уровня. Соответственно, при размыкании контакта мы рассчитываем получить на входе сигнал низкого уровня. Так ли это? Проверим.
Подключим кнопку по приведенной схеме и загрузим в Ардуино следующий скетч. Результат его работы посмотрим в мониторе порта.

void setup() {
  Serial.begin(9600);
  pinMode(2, INPUT);
}

void loop() {
  Serial.println(digitalRead(2));
  delay(1000);
}

При нажатии на кнопку Ардуино, действительно, зафиксирует на входе сигнал высокого уровня, при этом в монитор порта будет выводиться значение "1". Но при отпускании кнопки в мониторе порта будут выводиться как "0", так и "1". Я даже больше скажу: можно исключить из схемы кнопку (все равно она разомкнута), у нас останется только провод, подключенный к порту 2 Ардуино, результат опроса порта будет таким же непредсказуемым. Особенно это хорошо заметно с длинным куском провода. Почему так происходит? Дело в том, что вход Ардуино не подключен ни к линии питания, ни к земле - он находится "ни в каком" состоянии. Такое состояние называется высокоимпедансным или Z-состоянием. Провод в данном случае выполняет роль антенны, на которую оказывают воздействие окружающие ее электромагнитные поля. В результате Ардуино непредсказуемо фиксирует то высокий, то низкий уровень сигнала на данном входе.

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

Иногда подтягивающим называют резистор, который подтягивает именно к питанию, также используют англоязычный термин pull-up (pull-up резистор). А для обозначения резистора, подтягивающего к земле, можно использовать термин стягивающий или pull-down резистор. Ниже приведены схемы подключения кнопки к логическому входу (не обязательно Ардуино) с использованием подтягивающего и стягивающего резисторов.

Попробуйте подключить кнопку к Ардуино используя одну из приведенных схем. В этот раз в мониторе порта не будет никаких неожиданных значений.

Как вы понимаете, подтягивающие резисторы весьма востребованы в электронике. Они нужны не только для подключения кнопок, но также при подключении выводов устройств с Z-состоянием или открытым коллектором. Поэтому многие контроллеры имеют встроенные подтягивающие резисторы, в том числе и Ардуино (а точнее используемые в них микроконтроллеры). Чтобы подтянуть порт Ардуино к питанию необходимо функцией pinMode установить для данного порта режим INPUT_PULLUP. Давайте немного изменим схему и скетч из начала этой статьи. Из схемы уберем резистор и установим кнопку между вторым портом и землей:

А в скетче изменим режим работы порта на INPUT_PULLUP, чтобы задействовать внутренний подтягивающий резистор:

void setup() {
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP);
}

void loop() {
  Serial.println(digitalRead(2));
  delay(1000);
}

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

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

Что такое сильный (strong pull-up) и слабый (weak pull-up) подтягивающий резистор? Чем ниже сопротивление подтягивающего резистора, тем больший ток протекает через него и тем сильнее он подтягивает сигнал к питанию (или земле, если речь о pull-down резисторе). Отсюда и название сильный подтягивающий резистор. Соответственно, чем выше сопротивление, тем слабже резистор подтягивает сигнал, поэтому его называют слабым.

Как выбрать номинал для подтягивающего резистора? Общая рекомендация - это, как правило, 10кОм. Где-то от 5кОм и ниже считается сильной подтяжкой, 20..100кОм - слабая. Подтягивающие резисторы Ардуино имеют номинал 20..50кОм (конкретное значение подбирается и устанавливается на заводе изготовителе), т.е. являются слабыми. Поэтому в документации к различным устройствам можно увидеть рекомендации использовать более сильные подтягивающие резисторы. Особенно это актуально для устройств, работающих в неблагоприятных условиях или при значительной длине проводников, когда увеличивается вероятность возникновения электромагнитных помех.

Есть ли в Ардуино подтяжка к земле (внутренние pull-down резисторы)? - Нет. В Ардуино доступны только к подтягивающие к питанию резисторы. Поэтому если вам нужно подтянуть вывод к земле, то используйте для этого внешний резистор.

На этом всё. А дочитавшим до конца в качестве бонуса функциональная схема порта ввода/вывода микроконтроллера ATmega328P, используемого в Arduino UNO. На схеме показан подтягивающий резистор и условия для его включения:

  • бит PUD (PULLUP DISABLE) регистра MCUCR должен быть сброшен;
  • регистр DDxn (Data Direction) должен быть установлен в 0, т.е. порт сконфигурирован на ввод;
  • регистр PORTxn должен быть установлен в 1.


Схема порта ввода-вывода Ардуино. Подтягивающий резистор

28 комментариев:

  1. Друг ты опять спас меня, только из твоей статьи понял что если PULLUPом включаем подтягивающий резистор надо кидать контакт датчиков на землю. Весь русскоязычный интернет ато перешерстил. Спасибо.

    ОтветитьУдалить
    Ответы
    1. Узнал про подтягивающие из курса универа в PIC16, использовать в ардуино начну сегодня :D

      Удалить
  2. Получил Raspberry Pi и пользуюсь готовыми решениями с интернета, но ненмогу понять принципов работы, что очень напрягает (скорее раздражает). Ваш пост очень помог, хотя все ещё никакне могу понять две вещи:
    1. Разве резистор на 10к Ом не должен снижать напряжение до нулевых значений, что при подводе к вводу должен преобразовываться в 0?
    2. Почему при нажатии кнопки сигнал не разделяется и не поступает одновременно и на заземление и на ввод?

    ОтветитьУдалить
    Ответы
    1. А почему резистор должен снижать напряжение?
      Посмотрите на приведенную выше схему включения подтягивающего резистора. Когда кнопка разомкнута ток течет от VCC через резистор к микроконтроллеру - цифровой вход подтянут к питанию, на нем сигнал высокого уровня.
      Сопротивление порта микроконтроллера (в режиме INPUT) очень велико и при нажатии на кнопку ток пойдет по цепи с меньшим сопротивлением - через кнопку. Через цифровой вход ток уже не потечет, на нем будет сигнал низкого уровня.

      Удалить
  3. Спасибо за ответ, наконец то все понял. Странно что все это хорошо знал когда был школьником, а сейчас ума не приложу как все это работает... Хорошо что вы продолжаете поддерживать пост и читателей (особенно таких как я).

    ОтветитьУдалить
  4. Великая статья. А главное понятно мне начинающему.

    ОтветитьУдалить
  5. Привет Владимир !
    Очень хорошая статья , спасибо .

    ОтветитьУдалить
  6. Добрый день.
    С удовольствием читаю ваши статьи.
    Вопрос. Как влияют на энергопотребление подключение кнопки через стягивающий и подтягивающий резисторы?

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      Вообще увеличивают, ведь через них протекает ток. Тем больший, чем меньше сопротивление резистора. Но по этому поводу не стоит заморачиваться, если вы работаете с Ардуино: на ее фоне подтяжка не влияет на потребление. А вот когда вы пересядете с Ардуино на отдельные микроконтроллеры и начнете считать микроамперы, вот тогда можно обратить на этот вопрос внимание.

      Nick Gammon на странице http://www.gammon.com.au/power привел результаты своих измерений тока, потребляемого ATmega328P в режиме SLEEP_MODE_PWR_DOWN (BOD и ADC отключены) для различных состояний выводов:

      Все пины в режиме OUTPUT, LOW: 0.35 мкА.
      Все пины в режиме OUTPUT, HIGH: 1.86 мкА.
      Все пины в режиме INPUT, LOW (внутренние подтягивающие резисторы не задействованы): 0.35 мкА.
      Все пины в режиме INPUT, HIGH (задействованы внутренние подтягивающие резисторы): 1.25 мкА.

      Разница в последних двух результатах - это и есть потери на подтяжку всех выводов.

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

    Я сейчас в одном большом ступоре, если не сложно помогите, пожалуйста, определиться, какой контроллер (или систему) лучше взять за основу. Я биолог, но так получилось, что уже давно помимо прочего, отвечаю за сбор, хранение и обработку данных. Признаюсь сразу - программирование как таковое вызывает паралич мозга, но есть такое слово НАДО, поэтому уже 14 и 2 года соответственно у меня успешно работают две базы собранные на VB в Exel, из записей встроенного ридера, уроков "Планеты EXEL" и всякого разного не всегда цензурного….

    В общем, сперва почитал восторги на счет Ардуино, посмотрел FLProg (с души вроде не воротит, как XOD ID), в процессе Arduino IDE мелькает - тоже вроде бы явного отторжения не вызывает. Не нравиться два момента - цена кусается, и кушать все таки любит она, а с моим зрение боюсь даже светодиод отпаять будет проблематично. Второй взгляд был на STM32L0 - тут вроде бы и энергопотребление вкусное и часы реального времени тебе встроенные и... зашел еще на один ресурс БЛИН, уши в трубочку свернулись... и мозги-то народу ардуиной зс$р@ны и все эти ваши таблЭтки и примочки хуже чем инвалиды на всю жизнь бейсиком искалеченные и ниже -10 уже не работает и вообще… ИДИТЕ ВЫ!!! Не мешайте народу НОРМАЛЬНЫЕ языки программирования изучать, ПУСТЬ УЧАТ, а не это ваше всякое-разное!

    В общем аппаратная часть STM32 если честно нравиться, но как ее программировать и с какого боку прошивать, пока даже образно, если честно плохо понимаю, в то время как по Ардуино и в скетчах уже покопался и библиотеки посмотрел, логического шока вроде нет (пока). Вот и думаю имеет смысл углубляться в Ардуино среду или все же на какие-то другие контроллеры посмотреть? Например MSP430 еще рассматривал, но это я так понимаю еще одна среда и уже другая, значит и скетчи для датчиков не факт, что будут и библиотеки тоже, то есть все руками через регистры, что это такое я вроде бы (хотя не факт), а вот как руками делать пока увы не представляю.

    Сама задача из-за чего весь сыр-бор выглядит так, есть необходимость сделать простую, но гибкую метеосистему. Гибкую в том плане, что вот надо сейчас сделать регистратор температуры и влажности воздуха, что бы просыпался, допустим каждые 10 минут, снимал данные, писал на SD и засыпал, но при этом с автономным сроком работы хотя бы полгода и МАЛЕНЬКИЙ (грибники тырят блин) и все это в количестве штук 5-10 за не сильно астрономическую сумму (к слову посмотрел цены очень хороших датчиков SHT35 и приятно офигел, с модулями не сравнить). А завтра надо тоже самое, но плюс замер света и каждый час продувание камеры вентилятором (для учета транспирации), то есть уже не такое автономное (пара недель), не такое маленькое (может с батарейкой солнечной или даже с выводом данных по wi-fi/sim/радиоканалу), но что бы не с нуля и в той же системе?

    Про энергосбережение читал кстати очень внимательно, про прерывания тоже. Главная головная боль на данный момент, ОЧЕНЬ много информации о том, что из глубокого сна хорошо выходить по внешнему прерыванию, например с часов реального времени (выбрал DS3231), нашел даже связку блоков сон/пробуждение для FLProg, библиотеки вроде бы тоже есть. НО..., нигде не найду, хоть сколько ни будь, внятного объяснения куда в этом случае прописывать или ставить в визуальную среду этот самый внутренний будильник часов реального времени, как программировать его, способна ли сама программа после пробуждения его перепрограммировать на новое время и как запрограммировать ногу SQW на модуле, что бы она выдавала этот самый вожделенный сигнал на пробуждение платы...?

    Буду очень признателен, если хотя бы по общему направлению сориентируете - куда смотреть и что искать.

    ОтветитьУдалить
    Ответы
    1. Добрый день!
      С STM я не работал, поэтому сравнить с AVR не могу. Может оно было бы и лучше. Но Ардуино однозначно популярнее, для нее куча библиотек, примеров - на ней будет проще сделать. И если использовать не саму Ардуину, а отдельно микроконтроллер, то потребление будет реально низким. Проработать автономно год, периодически просыпаясь для опроса датчиков - запросто.

      Что касается flprog, то, мне кажется, для серьезных проектов он не очень. Лучше использовать нормальную IDE, в которой сам всё контролируешь.

      Так что мне видится следующее решение: AVR (ATmega328P) + DS3231 + датчики + на что писать показания (flash). Часы программируются на генерацию сигнала с нужным интервалом (10 минут), они будут выдавать его на SQW. Микроконтроллер при включении переводим в режим PowerDown, разрешив пробуждение по внешнему прерыванию - от DS3231. Проснувшись, запитываем датчики и память, читаем показания, пишем их в память, отключаем всех и снова спать до следующего сигнала будильника.

      Цена ATmega328P на Али меньше 100р. Потребление, как уже сказал, низкое: спать - хоть несколько лет; с учетом просыпаний - нужно иметь представление об общем потреблении системы, но батареи 1Ач на год-то должно хватить. Температурный диапазон -40..105C. Вполне нормальный МК для данной задачи.

      Удалить
    2. На ютубе есть несколько понятных видео по запросу "Метеостанция на Ардуино", можете сначала на ардуино повторить, понять логику работы, потом перекатываться на другие аппаратные платформы.

      Удалить
  8. Спасибо, уже тоже подумал, что с другими системами вряд ли сумею подружиться достаточно быстро, а если заказывать отдельно детали без лишних светодиодов и всяких преобразователей то даже с заказом плат и сборкой будет вроде бы не очень дорого (спасибо за статью с обвязкой контроллера).

    А можно еще вопрос, реально как-то в принципе определить, до какого минимального значения можно понизить тактовую частоту контроллера? Просто все эти мегагерцы когда у меня время отклика датчика влажности 8с...? И еще в какой-то статье Вы рассказали как заставить контроллер спать без прерываний по сторожевому таймеру, так же есть информация как отключать АЦП (датчики все цифровые, так что думаю мне он вообще не нужен) и контроль напряжения, а вот как отключить сам сторожевой таймер? Что бы он не просто не будил, а сам уснул и даже не дергался, если я правильно понял - это здорово экономит энергию.

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

    ОтветитьУдалить
    Ответы
    1. Я думаю, тут хватило бы 1-2 МГц. т.е. либо ставить соответствующий резонатор, либо тактироваться от внутреннего генератора 8МГц + деление частоты на 8 (фьюз CKDIV8). Второй вариант не требует резонатора и конденсаторов для него.

      Сторожевой таймер по умолчанию выключен, специально его выключать не нужно.

      И да, надо будет отключить АЦП и схему контроля питания для максимального энергосбережения.

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

      Удалить
  9. Да спасибо, я думал именно о тактировании от внутреннего резонатора с делением на 8, питание будет скорее всего от литиевой монетки на 3V типа CR2412 или CR2012, но вот еще вопрос возник - надо ли в схему ставить какой либо стабилизатор? Ну то есть по мере расхода и мало ли еще почему напряжение будет наверное падать, у microSD - 3.3V штатное, но вроде бы от 2.4-2.7 работает, часы реального времени DS3231 вроде бы такой батарейкой удовлетворяются, ну и датчик SHT35 номинальное 3.3, но минимум 2.15, в итоге вопрос надо ли какой-то стабилизатор-регулятор ставить, или можно обойтись как есть? Или допустим если стабилизировать на 3.3 можно ли этот стабилизатор как то программно отключать на время сна? Просто обычный линейный стабилизатор я насколько понимаю очень прожорливый, так вот если поставить импульсный и заводить его уже только на время работы схемы, а потом выключать и пусть МК спит просто от батарейки?

    ОтветитьУдалить
    Ответы
    1. Можно сделать так: МК питается от батарейки, а всё остальное от стабилизированных 3В. При уходе в сон МК будет отключать стабилизатор, такая возможность есть, наверное, у всех микросхем dc-dc преобразователей. В режиме сна они потребляют очень мало. Из подходящих приходит на ум микросхема HX3001. Да их много всяких.
      Насчет того нужен ли он вообще - это надо смотреть даташиты используемых компонентов и проверить на деле: запитать от регулируемого источника и постепенно уменьшать напряжение.
      3В таблетки, конечно, мало, у них емкость небольшая.

      Удалить
    2. Посмотрел стабилизатор - то что нужно, спасибо. А емкости таблетки, если я нигде не ошибся в расчетах, даже если на время активного режима повышать частоту до номинальных 8МГц (было где-то замечание, что на 1МГц датчик который планирую - опросить не удалось, хотя у него как раз такая частота указана в даташите), но даже в этом случае, пусть затратит система на каждый замер (активный режим) 0,1 с, и пусть даже меряет через каждую минуту, емкости 50мА/ч (аккумулятор) должно на 5,5 лет хватить, это нереально хорошо... )))

      Удалить
    3. Отключать контроллер вообще. По таймеру, раз, скажем в 10 минут, подаем питание на МК, он отрабатывает измерение-запись и отключает питание от себя. До следующего запуска таймером. Я бы взял, например, китайчик С005, там интервалы хоть до раз в год можно выставить.

      Удалить
  10. Добрый день! Подскажите пожалуйста, при написание скетча, сигналы на плату ардуино с нажатой кнопки при использовании разных типов подключения резисторов разные? Пытаюсь сформулировать вопрос PULL_UP----сигнал НАЖАТОЙ кнопки LOW, при PULL_DUWN----сигнал нажатой кнопки HIGH ????

    ОтветитьУдалить
    Ответы
    1. Добрый день.
      При разных подтяжках будут и разные уровни при считывании.

      "PULL_UP----сигнал НАЖАТОЙ кнопки LOW, при PULL_DUWN----сигнал нажатой кнопки HIGH"
      - Да. При условии, конечно, что кнопка при нажатии соединяет вход Ардуино с нужной шиной - питанием или землей.

      Удалить
  11. Потрясающе! Спасибо. Как хорошо, что я что-то заподозрил и поиском нашел эту статью. Пытаюсь разобраться с модулем INA226. Куча статей, половина авторов говорит нужно подтянуть к питанию пины A4, A5. Вторая половина ничего не говорит, но и о внутренней подтяжке не упоминает.

    ОтветитьУдалить
    Ответы
    1. Пожалуйста. Рад слышать, что статья помогла.
      Подтяжка линий I2C к питанию, конечно, нужна, это заложено в принципах работы шины. В Ардуино это требование выполняют внутренние подтягивающие резисторы. Они подключаются автоматически (а точнее их подключает за нас библиотека twi), когда мы пишем Wire.begin или ina226.begin() и т.п.

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

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

      Удалить
    2. Еще раз спасибо, Вы совершенно правы. Перечитал блоее внимательно все ссылки, которые нашел, да, ту схему, что я использовал, человек спаял вокруг голой микросхемы. Короче, собрал, всё работает ). Объясню зачем то мне. Захотелось мне замахнуться на плату от Texas нашего Instruments, но смущало меня, что очень она уж нежненькая, да и уровни напряжения не совпадают, а мне захотелось сразу серву подключить ) Написал в Texas, они намекнули, что неплохо бы даташиты читать и потыкали в два места в их документации. Для обоих целей нужно использовать полевой транзистор. Вот я и захотел узнать, какой ток протекает при открытии затвора. Всё ОК, 0.6 mA (а нужно не более 6 mA на ногу). И с напряжением проблема решилась, для открытия достаточно 3 В, столько сколько у ней на ноге.

      Удалить