# 蜂鳴器

## 一、蜂鳴器

蜂鳴器是很常用的一種發音的零組件，它分為有源和無源二種！本次以介紹無源蜂鳴器為主。雖然可以透過gpiozero的TonalBuzzer類別，很方便的去play某個音階，但是，了解什麼是方波，什麼是頻率(Hz)，並且自己動手實作自己的音階播放會更有成就感！

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

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

piano = list([261, 293, 329, 349, 391, 440, 493, 523])
buzzer = 17

gpio.setmode(gpio.BCM)
gpio.setup(buzzer, gpio.OUT)


def play(pitch, sec):
    half_pitch = (1 / pitch) / 2
    t = int(pitch * sec)
    for i in range(t):
        gpio.output(buzzer, gpio.HIGH)
        time.sleep(half_pitch)
        gpio.output(buzzer, gpio.LOW)
        time.sleep(half_pitch)


for p in piano:
    play(p, 1)

gpio.cleanup()
```

## 二、雙音蜂鳴器

樹莓派是單板電腦，加上Python是強大的程式語言，結合二者，就可以做到讓蜂鳴器同時發出二個音階，甚至可以讓二個、三個、四個蜂鳴器同時演奏。 本次的程式碼有點難度，要看懂它必須了解python的物件導向、物件繼承及Multi Threading多執行緒的概念，如果還沒有足夠的基礎而看不懂，也不要灰心，看看就好不用太在意，未來再慢慢打好python的程式能力即可。

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

```python
import RPi.GPIO as gpio
import time
from threading import Thread

piano1 = list([261, 293, 329, 349, 391, 440, 493, 523])
piano2 = list([261, 391, 329, 391, 261, 391, 329, 391])
buzzer = 17
buzzer2 = 27

gpio.setmode(gpio.BCM)


class PlayTone(Thread):
    def __init__(self, pin):
        super().__init__()
        self.pin = pin
        gpio.setup(self.pin, gpio.OUT)

    def tone(self, pitch, sec):
        half_pitch = (1 / pitch) / 2
        t = int(pitch * sec)
        for i in range(t):
            gpio.output(self.pin, gpio.HIGH)
            time.sleep(half_pitch)
            gpio.output(self.pin, gpio.LOW)
            time.sleep(half_pitch)


class Play(PlayTone):
    def __init__(self, pin, piano):
        super().__init__(pin)
        self.piano = piano

    def run(self):
        for p in self.piano:
            self.tone(p, 1)


p1 = Play(17, piano1)
p1.start()

p2 = Play(27, piano2)
p2.start()

while p1.is_alive():
    time.sleep(0.5)

gpio.cleanup()
```


---

# 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/feng-qi.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.
