Итак, посмотрим как GPIO работают на вход. Приблизительно можно представить GPIO(вход) как:
Не обращаем внимания на диоды, они всё равно не спасут. Резистор R1 может подключаться как pull-up или pull-down или вообще не участвовать, кстати, его сопротивление весьма приблизительно, оно лежит в диапазоне .
Чтобы избавиться от помех и дребезга на входной линии имеется триггер Шмитта (по умолчанию активен, можно отключить, но неясно зачем). Сейчас главное:
Попробуем использовать внутренний 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
Последнее нажатие пришлось на момент когда программа уже завершилась
Внешний резистор имеет то преимущество не требует программного включения и работает сразу.
В программе только убираем строчку включения pull-up резистора: pigpio.gpioSetPullUpDown(UsedGPIO.ButtonPin.pin, PI_PUD_UP)
Особой разницы для любительских проектов между pull-up и pull-down вариантами нет, хотя я отдаю предпочтению pull-up варианту. Если приходится размещать выключатель на длинных проводах, то гораздо спокойнее когда на этих проводах нет ничего, кроме GND. Кошка может разгрызть выключатель, перезамкнуть там все внутренности на корпус и на себя - ничего страшного, там везде GND.