تصویر شاخص نوشته: با بازر پیزو ملودی بساز: نت‌ها، فرکانس‌ها و کد

با بازر پیزو ملودی بساز: نت‌ها، فرکانس‌ها و کد

۱۷ شهریور ۱۴۰۵ خروجی‌ها و نمایشگرها

هر ملودی‌ای که تا حالا شنیده‌ای — از زنگِ گوشی تا سمفونی — روی یک ستون ایستاده: هر نُت، یک فرکانس است. «لا»ی وسطِ پیانو یعنی ۴۴۰ نوسان در ثانیه؛ این عدد سلیقه نیست، استانداردِ جهانیِ کوک است (ISO 16). پس اگر قطعه‌ای داشته باشی که فرکانسش دستِ توست، ساز داری — و بازر پیزوی پسیو دقیقاً همان قطعه است.

این نوشته از «جدولِ نت‌ها» تا یک ملودیِ واقعی با ESP32 می‌رود. کدها MicroPython‌اند و همه را می‌توانی بدونِ هیچ قطعه‌ای، در شبیه‌ساز اجرا کنی.

نت‌ها به زبانِ عدد

در موسیقیِ استاندارد، فرکانسِ نت‌ها با یک قاعدهٔ ریاضیِ مشخص چیده شده: هر اکتاو بالاتر، دوبرابرِ فرکانس (لای ۴۴۰ → لای اکتاوِ بعد ۸۸۰). فرکانس‌های یک اکتاوِ میانی، گِرد‌شده به هرتز:

نت دو ر می فا سل لا سی
فرکانس ۲۶۲ ۲۹۴ ۳۳۰ ۳۴۹ ۳۹۲ ۴۴۰ ۴۹۴

(اعداد از قاعدهٔ «هر نیم‌پرده ضربدر 2^(1/12)» می‌آیند — دستگاهِ هم‌ترازِ دوازده‌تایی؛ برای همین «دو»ی بعدی می‌شود ۵۲۳، یعنی دوبرابرِ ۲۶۲ منهای خطای گِردکردن.)

بازر برای پخشِ هر نت فقط باید موجی با همان فرکانس بگیرد — و تولیدِ موج با فرکانسِ دلخواه دقیقاً کارِ PWM است.

سلام، نتِ لا

from machine import Pin, PWM import time

buzzer = PWM(Pin(25)) buzzer.freq(440) # نت لا buzzer.duty(512) # موج روشن (نیمی از چرخه) time.sleep(1) buzzer.duty(0) # سکوت

سه سطرِ معنادار: فرکانس را بگذار، موج را روشن کن، بعد خاموش. duty(512) یعنی موجِ متقارنِ ۵۰٪ (بازهٔ duty در MicroPython اینجا ۰ تا ۱۰۲۳ است) — برای بازر بلندترین و تمیزترین انتخاب همین حوالی است، و «سکوت» یعنی duty صفر، نه قطعِ برنامه.

از نت به ملودی: آهنگ یعنی فهرست

ملودی چیزی نیست جز دنباله‌ای از (نت، مدت). پس ساختارِ داده‌اش را همان‌طور بنویس:

NOTES = {"C": 262, "D": 294, "E": 330, "F": 349, "G": 392, "A": 440, "B": 494, "C5": 523}

melody = [("E", 0.3), ("E", 0.3), ("F", 0.3), ("G", 0.3), ("G", 0.3), ("F", 0.3), ("E", 0.3), ("D", 0.3), ("C", 0.3), ("C", 0.3), ("D", 0.3), ("E", 0.3), ("E", 0.45), ("D", 0.15), ("D", 0.6)]

for name, dur in melody: buzzer.freq(NOTES[name]) buzzer.duty(512) time.sleep(dur * 0.9) # ۹۰٪ صدا buzzer.duty(0) time.sleep(dur * 0.1) # ۱۰٪ سکوت بین نت‌ها

این پانزده نت، جملهٔ اولِ «سرود شادیِ» بتهوون است — امتحانش کن. دو ظرافتِ مهندسی در همین حلقه پنهان است:

  • سکوتِ کوتاه بینِ نت‌ها (آن ۱۰٪): بدونش، دو نتِ پشت‌سرهمِ یکسان به هم می‌چسبند و یک نتِ بلند شنیده می‌شوند. گوش، مرزِ نت‌ها را از همین سکوت‌های ریز می‌فهمد.
  • مدت ضربدر ضریب: کلِ سرعتِ آهنگ را با یک عدد می‌بری بالا و پایین — همان کاری که موسیقی‌دان‌ها با «تمپو» می‌کنند.

چرا صدای بازر «تیز» است و صدای پیانو نه؟

چون بازر با موجِ مربعیِ PWM می‌خواند و پیانو با موجی نرم و مرکب. موجِ مربعی پُر از هارمونیک‌های اضافه است — به گوش «الکترونیکی و گزنده» می‌آید. این محدودیتِ صادقانهٔ این ساز است: بازر برای ملودی و هشدار عالی است، برای بازتولیدِ صدای واقعی نه؛ آن کار قطعهٔ دیگری می‌خواهد و مدارِ متفاوتی. همین محدودیت، آزمایشگاهِ خوبی هم هست — با تغییرِ duty از ۵۱۲ به مثلاً ۱۰۰، رنگِ صدا (نه نتش!) عوض می‌شود، چون شکلِ موج عوض شده. فرکانس نت را تعیین می‌کند، شکلِ موج «جنسِ» صدا را.

خودت بنواز — همین حالا

این کد را در شبیه‌سازِ آزمایشگاه یادستان اجرا کن: بازرِ پسیوِ واقعی شبیه‌سازی می‌شود و صدا از بلندگوی خودت درمی‌آید. نت عوض کن، تمپو دست بزن، ملودیِ خودت را بساز — این آزمایش فصلِ دهمِ ترمِ اولِ دورهٔ آیرو است، جایی که همین بازی تبدیل به آژیرِ رباتت می‌شود.

جمع‌بندی: ملودی = فهرستی از (فرکانس، مدت) + سکوت‌های ریزِ بین نت‌ها. استانداردِ ۴۴۰ هرتز برای «لا»، قاعدهٔ دوبرابر برای اکتاو، و PWM برای تولید — همین سه قطعه، بازرِ چندصدتومانی را به سازِ برنامه‌پذیر تبدیل می‌کند.