注釈

こんにちは、FacebookのSunFounder Raspberry Pi & Arduino & ESP32愛好者コミュニティへようこそ!Raspberry Pi、Arduino、ESP32について、他の愛好者とともにさらに深く学んでいきましょう。

参加する理由

  • 専門家のサポート: 購入後の問題や技術的な課題をコミュニティとチームのサポートで解決できます。

  • 学びと共有: ヒントやチュートリアルを交換して、スキルを高めましょう。

  • 独占プレビュー: 新製品の発表や先行情報をいち早く入手できます。

  • 特別割引: 最新製品に対する独占割引をお楽しみいただけます。

  • 祝祭プロモーションとギブアウェイ: ギブアウェイや季節限定のプロモーションに参加できます。

👉 一緒に探求し、創造してみませんか?今すぐ [こちら] をクリックして参加しましょう!

7.1 ライト・テルミンの作成

このワクワクするプロジェクトでは、Raspberry Pi Pico 2、フォトレジスタ(光センサー)、およびパッシブブザーを使用して ライト・テルミン を作成します。テルミンは、物理的に触れることなく演奏できるユニークな楽器で、演奏者の手の位置によって異なる音程を生成します。伝統的なテルミンを完全に再現することはできませんが、光の強さを音の周波数に変換することで、同様の機能をシミュレートできます。

必要なもの

このプロジェクトでは、以下のコンポーネントが必要です。

セットを購入するのが便利です。リンクはこちら:

名称

セット内容

リンク

Newton Lab Kit

450+

Newton Lab Kit

以下のリンクから個別に購入することもできます。

SN

コンポーネント

数量

リンク

1

Raspberry Pi Pico 2

1

購入

2

Micro USBケーブル

1

3

ブレッドボード

1

購入

4

ジャンパーワイヤー

数本

購入

5

LED

1

購入

6

トランジスタ

1(S8050)

購入

7

抵抗器

3個(1KΩ、220Ω、10KΩ)

購入

8

パッシブ ブザー

1個

9

フォトレジスター

1個

購入

コンセプトの理解

  • フォトレジスタ: 光の強さに基づいて抵抗値が変化するセンサー。光が強いと抵抗が低く、光が弱いと抵抗が高くなります。

  • パッシブブザー: 外部信号を必要とする音を出すデバイス。PWM(パルス幅変調)を使用して周波数を制御できます。

  • トランジスタ(S8050): 電流を増幅するために使用し、Picoから効率よくブザーを駆動します。

フォトレジスタからの値を読み取ることで、光の強さを音の周波数にマッピングできます。つまり、手をフォトレジスタの上にかざすと、ブザーから出る音程が変化し、テルミンのように演奏できます。

回路図

sch_light_theremin

プロジェクトを始める前に、フォトレジスタの上で手を上下に振って、光強度の範囲をキャリブレーションします。GP16に接続されたLEDはデバッグの時間を示し、LEDが点灯しているときはデバッグを開始したことを、消灯しているときはデバッグが終了したことを示します。

GP15が高レベルを出力すると、S8050(NPNトランジスタ)が導通し、パッシブブザーが鳴り始めます。

光が強いと、GP28の値は小さくなり、逆に光が弱いと、値は大きくなります。 フォトレジスタの値を使って、パッシブブザーの周波数を調整することで、光感応デバイスをシミュレートできます。

配線図

wiring_light_theremin

コードの記述

フォトレジスタから光強度を読み取り、それを周波数にマッピングし、ブザーでその周波数を再生するMicroPythonプログラムを作成します。

注釈

  • 7.1_light_theremin.pynewton-lab-kit/micropython から開くか、コードをThonnyにコピーして、「実行」ボタンを押すか、F5キーを押して実行してください。

  • 正しいインタープリタ(MicroPython (Raspberry Pi Pico).COMxx)が選択されていることを確認してください。

import machine
import utime

# コンポーネントの初期化
led = machine.Pin(16, machine.Pin.OUT)  # GP16に接続されたLED
photoresistor = machine.ADC(28)         # フォトレジスタ(GP28に接続)
buzzer = machine.PWM(machine.Pin(15))   # GP15に接続されたブザー

# キャリブレーション用の変数
light_low = 65535
light_high = 0

# 範囲を別の範囲にマッピングする関数
def interval_mapping(x, in_min, in_max, out_min, out_max):
    # in_minとin_maxが同じ値でないことを確認(ゼロ除算の防止)
    if in_max - in_min == 0:
        return out_min
    return int((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min)

# ブザーで音を鳴らす関数
def play_tone(pin, frequency):
    if frequency <= 0:
        pin.duty_u16(0)
    else:
        pin.freq(frequency)
        pin.duty_u16(32768)  # 50%のデューティサイクル

# キャリブレーションプロセス
def calibrate():
    global light_low, light_high
    print("Calibrating... Move your hand over the sensor.")
    led.value(1)  # LEDを点灯してキャリブレーション中であることを示す
    start_time = utime.ticks_ms()
    while utime.ticks_diff(utime.ticks_ms(), start_time) < 5000:  # 5秒間キャリブレーション
        light_value = photoresistor.read_u16()
        if light_value > light_high:
            light_high = light_value
        if light_value < light_low:
            light_low = light_value
        utime.sleep_ms(10)
    led.value(0)  # キャリブレーション後、LEDを消灯
    print("Calibration complete.")
    print("Light Low:", light_low)
    print("Light High:", light_high)

# メイン関数
def main():
    calibrate()
    try:
        while True:
            light_value = photoresistor.read_u16()
            # 光の値を周波数範囲にマッピング(例: 200Hz ~ 2000Hz)
            frequency = interval_mapping(light_value, light_low, light_high, 200, 2000)
            play_tone(buzzer, frequency)
            utime.sleep_ms(20)
    except KeyboardInterrupt:
        buzzer.deinit()
        print("Program stopped.")

# メイン関数の実行
if __name__ == "__main__":
    main()

コードが実行されると、LEDが点灯してキャリブレーション中であることを示します。

  • キャリブレーション:

    • 5秒間、フォトレジスタの上で手を動かしてキャリブレーションを行います。

    • これにより、プログラムは光の範囲を把握します。

  • テルミンの演奏:

    • キャリブレーションが終わると、LEDは消灯します。

    • フォトレジスタの上に手をかざすと、ブザーから音が鳴り、光強度に応じて音程が変わります。

    • 手の位置や動きで音を作り出してみましょう。

コードの理解

  1. 初期化:

    • LEDインジケーター: キャリブレーション中であることを示すために使用します。

    • フォトレジスタ: 光強度に対応するアナログ値を読み取ります。

    • ブザー: PWMを使用して、異なる周波数で音を生成します。

  2. キャリブレーション関数( calibrate() ):

    • 5秒間実行され、その間に最小値と最大値を記録します。

    • ユーザーに手を動かすよう指示し、光の範囲をキャプチャします。

    • LEDを視覚的なインジケーターとして使用します。

    # キャリブレーションプロセス
    def calibrate():
        global light_low, light_high
        print("Calibrating... Move your hand over the sensor.")
        led.value(1)  # LEDを点灯してキャリブレーション中であることを示す
        start_time = utime.ticks_ms()
        while utime.ticks_diff(utime.ticks_ms(), start_time) < 5000:  # 5秒間キャリブレーション
            light_value = photoresistor.read_u16()
            if light_value > light_high:
                light_high = light_value
            if light_value < light_low:
                light_low = light_value
            utime.sleep_ms(10)
        led.value(0)  # キャリブレーション後、LEDを消灯
        print("Calibration complete.")
        print("Light Low:", light_low)
        print("Light High:", light_high)
    
  3. 範囲マッピング関数( interval_mapping() ):

    • フォトレジスタの値を、ブザー用の周波数範囲にマッピングします。

    • ゼロ除算のエラーを防止します。

    # 範囲を別の範囲にマッピングする関数
    def interval_mapping(x, in_min, in_max, out_min, out_max):
        # in_minとin_maxが同じ値でないことを確認(ゼロ除算の防止)
        if in_max - in_min == 0:
            return out_min
        return int((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min)
    
  4. 音の再生( play_tone() ):

    • PWMを使用してブザーの周波数を設定します。

    • 周波数が0以下の場合、ブザーを停止します。

    # ブザーで音を鳴らす関数
    def play_tone(pin, frequency):
        if frequency <= 0:
            pin.duty_u16(0)
        else:
            pin.freq(frequency)
            pin.duty_u16(32768)  # 50%のデューティサイクル
    
  5. メインループ:

    • フォトレジスタから光値を継続的に読み取ります。

    • この値を周波数にマッピングします。

    • 周波数に対応する音を再生します。

    • 終了時にはエラーハンドリングを行い、後片付けをします。

    # メイン関数
    def main():
        calibrate()
        try:
            while True:
                light_value = photoresistor.read_u16()
                # 光の値を周波数範囲にマッピング(例: 200Hz ~ 2000Hz)
                frequency = interval_mapping(light_value, light_low, light_high, 200, 2000)
                play_tone(buzzer, frequency)
                utime.sleep_ms(20)
        except KeyboardInterrupt:
            buzzer.deinit()
            print("Program stopped.")
    

さらに実験してみましょう

  • 周波数範囲を調整:

    interval_mapping() 内の値を変更して、音程範囲を広げてみましょう。例えば、200Hz ~ 2000Hzを100Hz ~ 5000Hzに変更してみてください。

  • 視覚的なフィードバック:

    ピッチに応じて、追加のLEDを使用して視覚的なフィードバックを提供できます。

  • センサーを追加:

    もう一つのフォトレジスタを追加して、音量や他のパラメーターを調整してみましょう。

  • 音楽楽器の作成:

    他のセンサーや入力と組み合わせて、より複雑な楽器を作成できます。

限界の理解

  • 周囲の光:

    周囲の光の変化がパフォーマンスに影響を与える可能性があります。一定の照明を保つか、必要に応じて再キャリブレーションを行ってください。

  • センサーの感度:

    フォトレジスタは、急速な手の動きに対して素早く反応しない場合があります。

  • 音質:

    パッシブブザーは音質に限界があります。より良い音質を求める場合は、DAC出力付きのアクティブスピーカーの使用を検討してください。

結論

Raspberry Pi Pico 2を使ってライト・テルミンを作成することができました!このプロジェクトは、センサーとアクチュエーターを組み合わせて、インタラクティブで楽しい実験を作成する方法を示しています。引き続き、このプロジェクトを探求して、理解と創造力を深めていきましょう。