Изчитане на бутон с Raspberry Pi Pico и MicroPython

Изчитане на бутон с Raspberry Pi Pico и MicroPython

Въведение

Бутоните са едни от най-често използваните входни устройства в електронните проекти. Независимо дали разработвате система за управление, меню с бутони, алармена система, робот или IoT устройство, почти винаги се налага да прочитате състоянието на един или повече бутони.

В Raspberry Pi Pico това се реализира лесно чрез цифровите GPIO входове, които могат да използват вградените Pull-Up и Pull-Down резистори. Така отпада необходимостта от външни резистори в голяма част от проектите, което значително опростява схемата.

В тази статия ще разгледаме два различни начина за изчитане на бутон с Raspberry Pi Pico и MicroPython. Първият пример показва най-елементарния метод за откриване на натискане на бутон, а вторият демонстрира как може да се наблюдава суровото състояние на входа с висока честота на опресняване. Това ще ни помогне да разберем защо механичните бутони често генерират паразитни импулси (bounce) и защо в следващата статия ще използваме EMA-базиран филтър за тяхното надеждно елиминиране.


Свързване на бутон към Raspberry Pi Pico

В примерите използваме GPIO0 и вътрешния Pull-Up резистор. Пин-диаграмата и документацията на тази платформа мже да видите в нашето ревю: Raspberry Pi Pico – Малък, но Мощен Микроконтролер.

RaspberryPi_Pico-button-read

Свързването е изключително просто:

Извод на бутонаRaspberry Pi Pico
Единият изводGPIO0
Другият изводGND

При тази схема:

  • когато бутонът не е натиснат, GPIO входът е логическа единица (1);
  • когато бутонът се натисне, входът се свързва към маса и става логическа нула (0).

Използването на вътрешния Pull-Up резистор елиминира необходимостта от външен резистор и предотвратява “плаващо” състояние на входа.

Разгледайте аналогичната ни статия за изчитане на бутон с ESP8266: ESP8266 D1 Mini и MicroPython: изчитане на дигитален вход (бутон).


Основно цифрово изчитане на бутон с Raspberry Pi Pico

from machine import Pin
import time

# Configure button on GPIO 0 with an internal pull-down resistor
button = Pin(0, Pin.IN, Pin.PULL_UP)

while True:
    if button.value() == 0:
        print("Button pressed!")
    time.sleep(0.1) # Debounce delay

Обяснение на кода

Импортиране на необходимите модули

from machine import Pin
import time

Модулът machine предоставя достъп до GPIO пиновете, а time се използва за добавяне на кратки закъснения.


Конфигуриране на GPIO вход

button = Pin(0, Pin.IN, Pin.PULL_UP)

Тук се случват три важни неща:

  • избира се GPIO0;
  • пинът се конфигурира като вход (Pin.IN);
  • активира се вътрешният Pull-Up резистор (Pin.PULL_UP).

Това означава, че при ненатиснат бутон входът ще бъде логическа единица.


Проверка на състоянието

if button.value() == 0:

Функцията value() връща:

  • 1 – бутонът не е натиснат;
  • 0 – бутонът е натиснат.

Ако бъде открита логическа нула, програмата отпечатва съобщение.


Закъснение против многократно отчитане

time.sleep(0.1)

Добавя се пауза от 100 ms.

Това е най-елементарният начин за намаляване на многократните отчети при едно натискане на бутона. Макар да работи в прости проекти, този подход не премахва напълно проблема с механичния bounce.


Изчитане на суровия сигнал от бутон без филтриране

Следващият пример показва как изглежда реалният сигнал от бутона, без да се използва какъвто и да е алгоритъм за филтриране.

import machine
import time

# Инициализиране на бутон с вътрешен pull-up резистор на GPIO0
button = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP)

print("СТАРТ: Четене на СУРОВ сигнал (без филтри)")

# Променлива, за да следим предишната стойност и да печатаме само при промяна
last_raw_state = 1

while True:
    # 1. Четем директното, физическо състояние на пина (0 или 1)
    raw_state = button.value()
    
    # 2. Ако състоянието се е променило, го отпечатваме веднага
    if raw_state != last_raw_state:
        if raw_state == 0:
            print("Суров сигнал: 0 (НАТИСНАТ или ЕЛЕКТРИЧЕСКИ ШУМ)")
        else:
            print("Суров сигнал: 1 (ПУСНАТ или ЕЛЕКТРИЧЕСКИ ШУМ)")
            
        # Обновяваме последното състояние
        last_raw_state = raw_state
        
    # Бързо сканиране на всеки 5ms (същата скорост като при ЕМА филтъра)
    time.sleep(0.005)

Обяснение на кода

Следене на всяка промяна

Вместо непрекъснато да отпечатва състоянието на бутона, програмата извежда информация само когато бъде регистрирана промяна.

last_raw_state = 1

Тази променлива запомня последното известно състояние.


Прочитане на суровото състояние

raw_state = button.value()

Получава се директното състояние на GPIO входа точно в момента на измерването.


Проверка за промяна на състоянието

if raw_state != last_raw_state:

Ако бъде засечена промяна, тя веднага се отпечатва в терминала. Така могат да се наблюдават всички преходи между логическа единица и логическа нула.


Защо се появява електрически шум?

Механичните бутони не превключват моментално.

При натискане металните контакти започват да вибрират в продължение на няколко милисекунди. Вместо една чиста промяна се получава последователност от множество импулси.

Например едно натискане може да изглежда така:

111111101010101000000

Вместо:

111111100000000000000

Това явление е известно като Button Bounce или Contact Bounce.

Освен механичните трептения е възможно върху входа да се появят и краткотрайни електрически смущения, породени от околната среда или от захранването.


Бързо сканиране

time.sleep(0.005)

Входът се проверява на всеки 5 ms.

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

Именно тази скорост ще бъде използвана и в следващата статия, където ще приложим EMA-базиран филтър за надеждно премахване на случайните импулси и механичния bounce.


Обобщение

В тази статия разгледахме два различни подхода за цифрово изчитане на бутон с Raspberry Pi Pico и MicroPython.

Първият пример демонстрира най-лесния начин за откриване на натискане чрез използване на вътрешния Pull-Up резистор и кратко програмно закъснение. Този подход е напълно достатъчен за много любителски проекти и приложения, при които високата надеждност не е критична.

Вторият пример показва как изглежда суровият сигнал от механичен бутон без никакво филтриране. Благодарение на честото сканиране става ясно, че едно физическо натискане невинаги се превръща в един-единствен логически преход, а често съдържа множество краткотрайни импулси, породени от механичните контакти или електрически шум.


Заключение

Изчитането на бутон е една от най-базовите операции при разработката на вградени системи, но зад тази на пръв поглед проста задача се крият особености, които могат да доведат до неправилна работа на програмата. Макар кратките програмни закъснения да намаляват вероятността от многократно отчитане, те не решават напълно проблема с механичния bounce и електрическите смущения.

В следващата статия ще надградим настоящите примери, като използваме специално разработена EMA (Exponential Moving Average) библиотека за филтриране на цифровите входове. Тя ще осигури стабилно и надеждно разпознаване на натисканията, без необходимост от сложни алгоритми или допълнителни хардуерни компоненти.

Източници: RaspberryPi-Pico MicroPython, How to Read a Button with MicroPython.

Translate »