# 按鈕開關

## 一、輸入開關與上拉電阻

先介紹開關的基本電路概念，並說明各式各樣開關的種類，且為了能夠確保輸入腳位的電壓是高電位(1)或是低電位(0)，會增加一個電阻來達到目的，這個電阻位置若在輸入腳位上方稱為上拉電阻，若位置在腳位下方稱為下拉電阻。這個電阻的功用很重要喔！

{% embed url="<https://youtu.be/t6WpgUyQ9sQ>" %}

## 二、通用按鈕開關程式與按鈕事件

具有了關開的硬體知識後，撰寫程式來讀取開關值（高電位或低電位，也就是一般的1與0），之前介紹的都是輸出，比如點亮LED、啟動蜂鳴器等，這是第一次處理輸入的問題。 同時，按鈕通常會採用事件的方式來撰寫，因為「當按下時處理什麼工作」才是需要認真思考的邏輯，要更深入學習就必須了解事件的處理。

{% embed url="<https://youtu.be/A4ev4j8HO4w>" %}

```python
import RPi.GPIO as gpio
import time

wait_time = 0.2

gpio.setmode(gpio.BCM)

btn = 13
gpio.setup(btn, gpio.IN, pull_up_down=gpio.PUD_UP)

pre_status = None
pre_time = time.time()
current_time = None

try:
    while True:
        get_btn = gpio.input(btn)
        current_time = time.time()
        if get_btn == gpio.LOW and pre_status == gpio.HIGH and (current_time - pre_time) > wait_time:
            pre_time = current_time
            print('button pressed!', time.ctime())
        pre_status = get_btn
	time.sleep(0.3)
except KeyboardInterrupt:
    print('keyboard interrupt')
finally:
    gpio.cleanup()
```

## 三、自製MIDI按鈕電子琴(一)

蜂鳴器的聲音真的太難聽了，利用樹莓派本身強大的單板電腦能力，透過內建的timidity，發出美美的聲音。

&#x20;本次先介紹MIDI的基本概念，透過pygame這個強大的製作遊戲套件程式庫，呼叫midi播出美美的各式音色，另外樹莓派內建的音色不夠多，自行安裝fluid-soundfont-gm讓樹莓派可以演奏出更多的樂器音色。請打開終端機並輸入下列指令。

```
sudo apt install fluid-soundfont-gm
```

{% embed url="<https://youtu.be/KZ3HuH8JM9Q>" %}

```python
import pygame.midi
from time import sleep

pygame.midi.init()
player = pygame.midi.Output(2)
player.set_instrument(0)

player.note_on(60, 127)
sleep(1)
player.note_on(64, 127)
sleep(1)
player.note_on(67, 127)
sleep(3)
player.note_off(60)
player.note_off(64)
player.note_off(67)
player.close()

pygame.midi.quit()
```

## 四、自製MIDI按鈕電子琴(二)

有了MIDI的概念與操作基礎，正式結合gpiozero的button來實作出MIDI按鈕電子琴。

{% embed url="<https://youtu.be/PjsFN7_yahE>" %}

```python
from gpiozero import Button
import pygame.midi
from signal import pause

pins_notes = [(4, 60), (17, 64), (27, 67), (22, 72)]


class PainoButton(Button):
    def __init__(self, pin, note):
        super().__init__(pin)
        self.note = note

def playnote(btn):
    player.note_on(btn.note, 127)

def stopplay(btn):
    player.note_off(btn.note, 127)

pygame.midi.init()
player = pygame.midi.Output(2)
player.set_instrument(0)


painos = [PainoButton(pin, note) for pin, note in pins_notes]
for paino in painos:
    paino.when_pressed = playnote
    paino.when_released = stopplay

temp = input('按下enter鍵離開')

player.close()
pygame.midi.quit()
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://s761111.gitbook.io/raspi-sensor/an.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
