Yellow Rabbit

Контакты GPIO как входы

Raspberry Pi и кнопка

Итак, посмотрим как GPIO работают на вход. Приблизительно можно представить GPIO(вход) как: GPIO вход

Не обращаем внимания на диоды, они всё равно не спасут. Резистор R1 может подключаться как pull-up или pull-down или вообще не участвовать, кстати, его сопротивление весьма приблизительно, оно лежит в диапазоне .

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

Простая схема с внутренним pull-up резистором

Попробуем использовать внутренний pull-up резистор. Следовательно пока кнопка не нажата будет считываться высокий уровень. При нажатии кнопки будет считываться низкий уровень, учтём это в программе. Схема во внутренним pull-up резистором

Макетная плата

Текст программы:


package io.github.yrabbit.kotlin

import io.github.yrabbit.java.util.AddDir
import jpigpio.JPigpio
import jpigpio.JPigpio.*
import jpigpio.Pigpio
import jpigpio.Utils
import kotlinx.coroutines.experimental.cancelAndJoin
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
import kotlin.system.exitProcess

fun main(args: Array<String>) {
    AddDir.addDir("/home/rabbit/local/lib")
    println("*** Raspberry Pi Kotlin ***")
    val pigpio = Pigpio()
    pigpio.gpioInitialize()
    Utils.addShutdown(pigpio)
    normOutputDriveStrength(pigpio)

    // Set pull-up resistor on button GPIO
    pigpio.gpioSetPullUpDown(UsedGPIO.ButtonPin.pin, PI_PUD_UP)

    // Init LED gpio
    pigpio.gpioSetMode(UsedGPIO.LedPin.pin, PI_OUTPUT)

    runBlocking {
        val job = launch {
            while (isActive) {
                with(pigpio) {
                    gpioWrite(UsedGPIO.LedPin.pin, !gpioRead(UsedGPIO.ButtonPin.pin))
                }
            }
        }
        // wait
        delay(8 * 1000)
        job.cancelAndJoin()
    }

    // clean up
    gpioSwitchToInput(pigpio)
    println("done.")
    exitProcess(0)
}

fun normOutputDriveStrength(pigpio: JPigpio) {
    // Check drive strength on GPIO
    val strength = pigpio.gpioGetPad(0)

    if (strength != CURRENT) {
        pigpio.gpioSetPad(0, CURRENT)
    }
}

/*
 * Clean up
 */
fun gpioSwitchToInput(pigpio: JPigpio) {
    UsedGPIO.values().forEach {
        pigpio.gpioSetMode(it.pin, PI_INPUT)
    }
}

enum class UsedGPIO(val pin: Int) {
    ButtonPin(5),   // GPIO05
    LedPin(26)      // GPIO26
}

const val CURRENT = 8 // mA

Запускаем

Последнее нажатие пришлось на момент когда программа уже завершилась:smiley:

Внешний pull-up резистор

Внешний резистор имеет то преимущество не требует программного включения и работает сразу. Схема с внешним резистором

Макетная плата

В программе только убираем строчку включения pull-up резистора: pigpio.gpioSetPullUpDown(UsedGPIO.ButtonPin.pin, PI_PUD_UP)

Как это работает

Pull-down резисторы

Схема с pull-down резистором

Особой разницы для любительских проектов между pull-up и pull-down вариантами нет, хотя я отдаю предпочтению pull-up варианту. Если приходится размещать выключатель на длинных проводах, то гораздо спокойнее когда на этих проводах нет ничего, кроме GND. Кошка может разгрызть выключатель, перезамкнуть там все внутренности на корпус и на себя - ничего страшного, там везде GND. Кошка в проводах