> For the complete documentation index, see [llms.txt](https://s761111.gitbook.io/raspi-sensor/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://s761111.gitbook.io/raspi-sensor/an.md).

# 按鈕開關

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

先介紹開關的基本電路概念，並說明各式各樣開關的種類，且為了能夠確保輸入腳位的電壓是高電位(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()
```
