Пассивный пьезозуммер и tone(): мелодии на Arduino
Классическая ловушка новичка: заказал «зуммер для ардуино», подключил, подал HIGH — а пищит одна нота и всё. Мелодию такой зуммер не сыграет никогда, потому что это активный зуммер: генератор внутри, он умеет только «пи». Пассивный пьезозуммер (KY-006) — наоборот: внутри голая пьезомембрана, и частоту задаёте вы — tone(пин, частота) превращает его в динамик, который играет хоть сирену, хоть тему Марио.
Ниже — одна секунда проверки, какой зуммер у вас в руках, тонкости tone() и noTone(), мелодия по массиву нот и честные ограничения: на Uno мелодия одна за раз, а ШИМ на двух пинах при этом глохнет. KY-006 лежит в палитре «Макетка» нашего симулятора — попробуйте его в симуляторе и сыграйте мелодию до покупки.
Активный против пассивного: проверка за одну секунду
Залейте скетч digitalWrite(пин, HIGH) без всяких библиотек: активный зуммер загудит ровной нотой, пассивный щёлкнет один раз и замолчит. Всё, определение готово. Дальше таблица, чтобы понимать, что вы купили и что оно умеет:
| Параметр | Активный зуммер | Пассивный KY-006 |
|---|---|---|
| Внутри | генератор частоты на плате | только пьезомембрана |
| Запуск | digitalWrite(пин, HIGH) | tone(пин, частота) |
| Мелодии | одна нота, навсегда | любые частоты 31 Гц - 65 кГц |
| Код | две строки | массив нот |
| Сигнал покоя | пищит от постоянного HIGH | молчит: DC для него тишина |
| Цена | 20-40 ₽ | 15-30 ₽ |
Нюанс, который путает всех: у активного и пассивного одинаковое подключение — плюс к пину, минус к GND (или наоборот, смотрите маркировку). Разница только в коде. Разбор обоих типов с резистором и громкостью — в старом лендинге про пьезоизлучатель; здесь копаем глубже в tone().
tone() и noTone(): как это работает
tone(пин, частота) стартует прямоугольник заданной частоты на пине, tone(пин, частота, длительность) — то же с автовыключением через заданные миллисекунды, noTone(пин) глушит сразу. Мембрана дёргается с частотой сигнала — воздух дрожит — слышится нота. Частоты нот лежат в любой таблице: до пятой октавы 523 Гц, ре 587, ми 659, фа 698, соль 784. Цена гибкости: tone() занимает таймер Timer2, и за раз играет только одна мелодия на одном пине. Второй вызов tone() перенастроит таймер — первая нота замолчит. И главное по граблям: вместе с Timer2 глохнет ШИМ на пинах 3 и 11 — если у вас диммер на D3, во время мелодии он перестанет регулироваться.
Мелодия: массив нот и массив длительностей
const byte PIN_PIEZO = 8; // частоты нот (Гц): до-ре-ми-фа-соль-ми-до, 0 = паузаconst int MELODY[] = { 523, 587, 659, 698, 784, 659, 523, 0 };const byte BEAT[] = { 25, 25, 25, 25, 50, 25, 50, 15 }; // длит. ×10 мс void setup() { } void loop() { for (byte i = 0; i < 8; i++) { int dur = BEAT[i] * 10; if (MELODY[i] > 0) { tone(PIN_PIEZO, MELODY[i], dur - 20); // 20 мс отрыва между нотами } else { noTone(PIN_PIEZO); // пауза — тоже нота } delay(dur); } noTone(PIN_PIEZO); delay(1500);}Почему tone() с третьим аргументом, а не delay между двумя: длительность в tone() освобождает вас от точного расчёта, но паузу-отрыв между нотами в 20 мс всё равно стоит оставить — без неё соседние ноты сливаются в гудение. Полный разбор техники с таблицей частот целых двух октав — в уроке про мелодию через массив, а ловушки таймеров в сложных проектах — в уроке про конфликты tone и таймеров.
Ограничения tone() на Uno
- Одна мелодия за раз: таймер один, второй tone() убивает первый.
- ШИМ на пинах 3 и 11 глохнет, пока tone() играет — общий Timer2.
- Библиотеки, которые тоже садятся на Timer2 (ИК-приёмник IRremote), конфликтуют с tone().
- Частоты ниже 31 Гц не играются — порог функции на Uno.
- Громкость tone() не регулируется: пьезо тихое по природе, громкость делают резонатором в корпусе.
Применения кроме музыки: сигнализация по датчику Холла на двери, сигнал «бак полон» с датчика уровня воды, клики интерфейса. Если нужен не звук, а тихий сигнал в кармане — вибромотор на ШИМ играет ту же мелодию эксцентриком. А проверить tone() без железа можно и в отдельном симуляторе зуммера.