Работа с вводом: читаем состояние кнопки

Введение #

После освоения управления выходными сигналами (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).

  1. Подключите пин №11 к аноду светодиода (через резистор ~220 Ом), а катод светодиода — к GND (как и раньше).
  2. Подключите одну ножку кнопки к пину №7.
  3. Подключите противоположную ножку кнопки к любому пину 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. Результат будет таким же, как и в предыдущем примере: светодиод загорается при нажатии на кнопку. Однако теперь ваша схема стала проще, а вся логика по обеспечению стабильного состояния пина перенесена в программный код.


254 просмотров0 комментариев

Комментарии (0)

Для участия в обсуждении Вы должны быть авторизованным пользователем
Разделы

Навигация

ВойтиРегистрация