Введение #
После освоения управления выходными сигналами (output
), следующим логическим шагом является получение данных из внешнего мира. GPIO-контакты, сконфигурированные как вход (INPUT
), позволяют системе отслеживать напряжение на пине и интерпретировать его как логический HIGH
(высокий уровень) или LOW
(низкий уровень). Основной функцией для этого является GPIO.input()
.
Фундаментальная проблема: "Плавающий" вход
При работе с пинами в режиме входа возникает критически важный нюанс, известный как неопределенное, или "плавающее" состояние (floating state).
Если входной пин ни к чему не подключен или подключен к разомкнутой цепи (например, к отжатой кнопке), его логический уровень не является ни HIGH
, ни LOW
. Он становится похож на флюгер на ветру, будучи крайне чувствительным к любым внешним электромагнитным наводкам. Это приводит к тому, что программа может считывать хаотичные, случайные значения, что делает невозможным получение достоверных данных.
Решение: Подтягивающие и стягивающие резисторы
Для борьбы с неопределенностью пину необходимо задать состояние по умолчанию. Это делается с помощью резисторов, которые "притягивают" уровень пина к HIGH
или LOW
, когда на него не воздействует внешний сигнал. Существует два способа реализации этого: внешний (с помощью физического резистора) и внутренний (используя встроенные в процессор резисторы).
Способ 1: Внешний стягивающий резистор (Классический подход) #
Этот метод является каноническим в цифровой электронике и обеспечивает максимальную надежность. Вы вручную добавляете в схему физический резистор, который гарантирует стабильное состояние пина.
- Стягивающий резистор (Pull-Down): Внешний резистор подключается между GPIO-пином и землей (
GND
). Если никакое другое напряжение на пин не подается, этот резистор будет "стягивать" его уровень кLOW
. - Подтягивающий резистор (Pull-Up): Альтернативный вариант, где резистор подключается между пином и питанием (
3.3V
). В этом случае состояние по умолчанию было быHIGH
.
В примере ниже мы рассмотрим классическую схему со стягивающим резистором (Pull-Down).
Практический пример: Чтение кнопки с внешним резистором
1. Аппаратная часть:
- Repka Pi
- Макетная плата (Breadboard)
- Тактовая кнопка
- Светодиод
- Два резистора (один для светодиода, ~220 Ом; второй для стяжки, ~10 кОм)
- Соединительные провода
2. Схема подключения Внимательно соберите схему, как показано на рисунке ниже.
Пояснения к схеме:
- Питание и земля: Красная и черная линии на макетной плате (по краям) подключены к 3.3V и GND Repka Pi (физические пины 1 и 6).
- Схема светодиода: Светодиод подключен к пину №11 через токоограничивающий резистор (зеленая линия), а затем к GND (черная линия).
- Схема кнопки (с Pull-Down резистором):
- Одна ножка кнопки подключена к пину №7 (синяя линия).
- К этой же ножке подключен один конец стягивающего резистора (~10 кОм), другой конец которого идет на GND (черная линия).
- Противоположная ножка кнопки подключена к 3.3V (красная линия).
Логика схемы: Когда кнопка не нажата, стягивающий резистор соединяет пин №7 с землей, поэтому его состояние по умолчанию — LOW
. Когда вы нажимаете кнопку, она замыкает пин на 3.3V, и его состояние становится HIGH
.
Программный код (read_button_external.py
)
# -*- coding: utf-8 -*-
import RepkaPi.GPIO as GPIO
from time import sleep
# --- 1. Настройка ---
# Используем физическую нумерацию пинов, как на схеме
GPIO.setmode(GPIO.BOARD)
# Определяем пины для кнопки и светодиода согласно схеме
BUTTON_PIN = 7
LED_PIN = 11
# Настраиваем пин светодиода как ВЫХОД
GPIO.setup(LED_PIN, GPIO.OUT)
# Настраиваем пин кнопки как ВХОД.
# ПАРАМЕТР pull_up_down НЕ УКАЗЫВАЕМ, так как он реализован внешним резистором.
GPIO.setup(BUTTON_PIN, GPIO.IN)
# --- 2. Основной цикл ---
try:
print("Программа запущена. Нажмите кнопку, чтобы зажечь светодиод.")
print("Нажмите CTRL+C для выхода.")
while True:
# Считываем состояние пина кнопки
button_state = GPIO.input(BUTTON_PIN)
# Проверяем состояние. Так как мы используем Pull-Down,
# нажатие кнопки приведет к состоянию HIGH.
if button_state == GPIO.HIGH:
# Кнопка нажата - включаем светодиод
GPIO.output(LED_PIN, GPIO.HIGH)
else:
# Кнопка не нажата - выключаем светодиод
GPIO.output(LED_PIN, GPIO.LOW)
sleep(0.05) # Небольшая задержка для снижения нагрузки на процессор
# --- 3. Очистка ---
except KeyboardInterrupt:
print("\nЗавершение работы.")
finally:
GPIO.cleanup() # Сбрасываем состояние всех использованных пинов
Способ 2: Внутренний подтягивающий резистор (Программный подход) #
Процессоры Allwinner, на которых построены платы Repka Pi, содержат встроенные, программируемые резисторы. Библиотека RepkaPi.GPIO
позволяет управлять ими напрямую из вашего Python-кода. Это значительно упрощает схему, так как исчезает необходимость в физическом стягивающем/подтягивающем резисторе.
Этот метод требует, чтобы ваша программа была запущена с правами sudo
или чтобы был настроен и работал фоновый сервис, который мы реализовали.
Практический пример: Чтение кнопки с внутренним резистором
Давайте решим ту же задачу, но уже без лишних компонентов на макетной плате.
1. Аппаратная часть:
- Repka Pi
- Тактовая кнопка
- Светодиод
- Один резистор (только для светодиода, ~220 Ом)
- Соединительные провода
2. Схема подключения (упрощенная) В этом примере мы используем внутренний подтягивающий резистор (Pull-Up).
- Подключите пин №11 к аноду светодиода (через резистор ~220 Ом), а катод светодиода — к GND (как и раньше).
- Подключите одну ножку кнопки к пину №7.
- Подключите противоположную ножку кнопки к любому пину GND (например, к пину №9).
Логика схемы: Мы программно "подтянем" пин №7 к 3.3V. Когда кнопка не нажата, на пине будет состояние HIGH
. Когда вы нажимаете кнопку, она замыкает пин на землю (GND
), и его состояние становится LOW
.
3. Программный код (read_button_internal.py
)
# -*- coding: utf-8 -*-
import RepkaPi.GPIO as GPIO
from time import sleep
# --- 1. Настройка ---
GPIO.setmode(GPIO.BOARD)
BUTTON_PIN = 7
LED_PIN = 11
# Настраиваем пин светодиода как ВЫХОД
GPIO.setup(LED_PIN, GPIO.OUT)
# --- ГЛАВНОЕ ИЗМЕНЕНИЕ ---
# Настраиваем пин кнопки как ВХОД и сразу же включаем
# внутренний ПОДТЯГИВАЮЩИЙ резистор к питанию.
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# -------------------------
# --- 2. Основной цикл ---
try:
print("Программа запущена. Нажмите кнопку, чтобы зажечь светодиод.")
print("Нажмите CTRL+C для выхода.")
while True:
button_state = GPIO.input(BUTTON_PIN)
# Проверяем состояние. Так как мы используем Pull-Up,
# нажатие кнопки приведет к состоянию LOW.
if button_state == GPIO.LOW:
# Кнопка нажата - включаем светодиод
GPIO.output(LED_PIN, GPIO.HIGH)
else:
# Кнопка не нажата - выключаем светодиод
GPIO.output(LED_PIN, GPIO.LOW)
sleep(0.05)
# --- 3. Очистка ---
except KeyboardInterrupt:
print("\nЗавершение работы.")
finally:
# Cleanup корректно сбросит и подтяжку
GPIO.cleanup()
Запуск и результат #
Запустите скрипт python3 read_button_internal.py
. Результат будет таким же, как и в предыдущем примере: светодиод загорается при нажатии на кнопку. Однако теперь ваша схема стала проще, а вся логика по обеспечению стабильного состояния пина перенесена в программный код.