Mali sintisajzer: potenciometar i pasivni piezo

Drži taster da sviraš i potenciometrom mijenjaj visinu tona od 200 do 2000 Hz. Poveži piezo drajver i pretvori analogno očitavanje u frekvenciju.

Zvuk, releji i interaktivni projektiPočetni nivo90 min

Ciljevi učenja

  • Provjeriti da pasivni zvučni element odgovara piezo referenci i pobudi 0–5 V.
  • Povezati tranzistor, paralelni otpornik za pražnjenje i serijski otpornik za ograničavanje impulsa.
  • Mapirati 12-bitno analogno očitavanje na frekvenciju tona.
  • Upravljati tonom pomoću pin-based LEDC API-ja i stabilnog stanja tastera.

Prije početka

Kurs 05: potenciometar i ADC. Kurs 13: tranzistorsko upravljanje buzzerom, polaritet diode i taster. Koristi se klasični ESP32 i Arduino-ESP32 3.3.12.

Referentna postavka

Ploča u Arduino IDE-u
ESP32 Dev Module
Arduino-ESP32
3.3.12
Serial Monitor
115200 baud

Ovo je referentni profil, a ne identifikacija ploče sa fotografije. Za ESP32-C3/S2/S3 ili drugačije označenu ploču treba prilagoditi GPIO i provjeriti šemu prije spajanja.

Šta pravimo?

Pravimo jednostavan instrument: držiš taster da bi se čuo ton, a potenciometrom mijenjaš njegovu visinu. ESP32 stvara električni signal frekvencije od 200 do 2000 Hz. Kada otpustiš taster, instrument utihne.

U ovom kursu koristimo pasivni piezoelektrični zvučni element. On prima spoljašnji signal koji određuje ton. Zato možeš povezati očitanu analognu vrijednost, matematičku formulu i promjenu koju odmah čuješ.

Ciljevi i predznanje

Potrebni su kurs 05, za potenciometar i analogno očitavanje, i kurs 13, za tranzistorski prekidač i taster. Predviđeno vrijeme je oko 90 minuta.

Naučićeš da izabereš odgovarajući pasivni element, objasniš ulogu otpornika za pražnjenje, mapiraš ADC vrijednost u frekvenciju i koristiš Arduino-ESP32 LEDC API. Poseban cilj je da razlikuješ visinu tona, određenu frekvencijom, od njegove glasnoće.

Potrebna oprema i izbor piezo elementa

KomponentaKoličinaSpecifikacija i napomene
ESP32 razvojna ploča sa klasičnim ESP32-WROOM-32 modulom1GPIO nazivi moraju odgovarati referentnom profilu; fizički položaj izvoda provjeriti na ploči.
USB kabl za podatke i napajanje1Priključak prilagoditi ploči; komplet na slici navodi Micro-USB.
Eksperimentalna ploča1Komplet navodi 830 kontaktnih tačaka. Provjeriti eventualni prekid naponskih vodova.
Pasivni buzzer — referentni piezo element1Fotografija navodi pasivni buzzer, ne njegov tip. Ova šema zahtijeva piezo za pobudu 0–5 V; magnetni pretvarač zahtijeva zasebno usklađivanje.
Dodatni NPN tranzistor PN2222A1Obavezno dodatno — nije na slici kompletaDODATNO, nije naveden u kompletu. Identifikuj B/C/E prema tačnom proizvođaču; PN2222A i P2N2222A mogu imati različit raspored.

DODATNO: tranzistor nije naveden na fotografiji kompleta.

Dodatna zaštitna dioda 1N41481Obavezno dodatno — nije na slici kompletaDODATNO, nije navedena u kompletu. Prsten označava katodu K. U buzzer krugu katoda ide prema +5 V.

DODATNO: dioda nije navedena na fotografiji kompleta.

Otpornik 1 kΩ2Otpornik baze; u kursu 14 i paralelni otpornik piezo elementa. Količina ove vrijednosti u kompletu nije potvrđena.
Otpornik 10 kΩ1R2 je pull-down od baze Q1 prema GND; baza ostaje nisko dok GPIO ne upravlja.
Otpornik 220 Ω1R4 je serijski otpornik između BZ1.MINUS i Q1.C; ograničava impuls punjenja piezo elementa.
Trenutni taster1Koristiti par priključaka koji se spaja pritiskom; ista strana četvoronožnog tastera može već biti spojena.
Potenciometar 10 kΩ1Dva krajnja izvoda i klizač W; raspored utvrditi prema stvarnoj komponenti.
Spojni kablovi13M-M ili F-M prema priključcima ploče.

Okvirna količina; zavisi od fizičkog rasporeda.

PN2222A tranzistor i dioda 1N4148 dodatne su obavezne komponente koje nisu prikazane u fotografisanom kompletu. Pasivni element iz kompleta nije potvrđen kao piezoelektrični samo na osnovu fotografije. Za ovu šemu koristi provjeren pasivni piezo pretvarač predviđen za pravougaonu pobudu 0–5 V.

Ako oznaka ili tehnički list ne potvrđuju tip i pobudu, prvo identifikuj dio. Aktivni buzzer ima sopstveni oscilator, a magnetni pasivni pretvarač zahtijeva posebno usklađen sklop. Nisu automatske zamjene za našu referencu.

Frekvencija i visina tona

Frekvencija govori koliko se perioda ponavlja u sekundi. Pri 200 Hz period traje 5 ms; pri 2000 Hz traje 0,5 ms. Veća frekvencija se u ovom opsegu uglavnom čuje kao viši ton.

LEDC periferija proizvodi signal, dok glavni program očitava potenciometar i taster. Funkcija ledcWriteTone() koristi faktor ispune od 50%. Time se određuje odnos trajanja dva dijela perioda, a ne jednaka glasnoća pri svim frekvencijama. Stvarni piezo element neke frekvencije pretvara u zvuk efikasnije od drugih.

Zašto dopunjujemo sklop iz kursa 13?

Piezo element električno ima kapacitivno ponašanje. R3 od 1 kΩ, postavljen paralelno sa njim, omogućava pražnjenje kada se tranzistor isključi. Proizvođač Murata objašnjava ovu ulogu paralelnog otpornika. Dioda nije zamjena za R3.

Dodajemo i R4 od 220 Ω u put ka kolektoru. On ograničava strujne impulse punjenja: za nominalnih 5 V procjena početne granice iznosi 5/220 ≈ 23 mA. U ustaljenom uključenom stanju R3 i R4 daju približno 5 × 1000/1220 ≈ 4,1 V na piezo elementu, uz zanemaren pad na tranzistoru. To su proračunske procjene; stvarni talas zavisi i od frekvencije i kapacitivnosti.

Šema i provjera napajanja

Šema povezivanja

Referenca je pasivni piezo element za pobudu 0–5 V; fotografija ne potvrđuje da je buzzer iz kompleta piezo. R3 od 1 kΩ je paralelni put pražnjenja. R4 od 220 Ω je serijski između BZ1.MINUS i Q1.C. D1 je preko piezo elementa, prije R4. Q1 i D1 su dodatni.

Šema povezivanja — električne veze navedene u tabeli ispod
Šema povezivanjaUvećajSVGPNG
Veze · Šema povezivanja
OdDoOpis veze
ESP32.GPIO26R1.1Otpornik R1 od 1 kΩ ograničava struju baze.
R1.2Q1.BBaza dodatnog PN2222A tranzistora.
Q1.BR2.1R2 od 10 kΩ drži bazu nisko dok GPIO ne upravlja.
R2.2ESP32.GNDDrugi kraj pull-down otpornika.
Q1.EESP32.GNDEmiter prema zajedničkoj masi; provjeriti stvarni B/C/E raspored.
ESP32.USB5VBZ1.PLUSProvjereni USB vod 5 V prema pozitivnom izvodu buzzera.
D1.KESP32.USB5VKatoda zaštitne 1N4148, označena prstenom, prema +5 V.
BZ1.MINUSR4.1R4 od 220 Ω je između piezo sklopa i kolektora; ograničava impuls punjenja.
R4.2Q1.CDrugi kraj serijskog R4 prema kolektoru.
D1.ABZ1.MINUSAnoda diode na MINUS strani piezo elementa, prije R4.
BZ1.PLUSR3.1R3 od 1 kΩ je paralelno piezo elementu.
R3.2BZ1.MINUSR3 zatvara put pražnjenja između PLUS i MINUS.
ESP32.GPIO27SW1.CONTACT_ATaster na ulaz sa INPUT_PULLUP.
SW1.CONTACT_BESP32.GNDDrugi izvod odabranog para kontakata, koji se spaja pritiskom.
ESP32.3V3RV1.END_AJedan krajnji izvod potenciometra 10 kΩ.
ESP32.GNDRV1.END_BDrugi krajnji izvod.
RV1.WESP32.GPIO34Klizač prema ulazu ADC1.

B, C i E označavaju funkcije izvoda Q1. Fizički redoslijed utvrdi iz tehničkog lista tačnog PN2222A dijela, bez zaključivanja samo prema ravnoj strani kućišta.

Koristi USB kao jedini izvor napajanja ploče. Piezo grana ide na dokumentovano USB 5 V napajanje; potenciometar ide na 3,3 V. Provjeri strujnu mogućnost USB priključka i ploče. Ne dodaj paralelno drugi izvor 5 V. GPIO34 je analogni ulaz, pa klizač potenciometra nikada ne povezuj na 5 V.

Spajanje korak po korak

  1. Isključi USB. Spoji GND ploče, emiter Q1 i zajedničku masu.
  2. Poveži GPIO26 preko R1 od 1 kΩ sa bazom. Dodaj R2 od 10 kΩ između baze i mase.
  3. Poveži plus BZ1 na USB 5 V. Označi čvor na njegovom minusu kao X.
  4. Poveži R3 od 1 kΩ između plusa BZ1 i čvora X: on je paralelan sa piezo elementom.
  5. Spoji čvor X preko R4 od 220 Ω na kolektor Q1. Ovdje nema direktne žice od minusa BZ1 do kolektora.
  6. Dodaj D1: anoda na X, katoda sa prstenom na plus/5 V. Dioda ostaje neposredno preko BZ1, prije R4.
  7. Spoji krajnje izvode RV1 od 10 kΩ na 3V3 i GND, a klizač na GPIO34.
  8. Poveži prekidački par tastera između GPIO27 i GND. Provjeri sve veze prije ponovnog priključivanja USB-a.

Priprema Arduino okruženja

Koristi Arduino IDE 2.x, esp32 by Espressif Systems 3.3.12, ploču ESP32 Dev Module za klasični ESP32/WROOM-32 i Serial Monitor na 115200 baud. Otvori passive_synth.ino iz istoimenog direktorijuma. Dodatne biblioteke nisu potrebne.

Ovaj program koristi pozive LEDC API-ja za Arduino-ESP32 3.x, u kojima se navodi pin. Ne zamjenjuj ih starim primjerima sa ledcSetup() iz prethodnih verzija jezgra.

Kompletan program

passive_synth.ino Arduino / C++
Preuzmi .ino

#include <Arduino.h>

constexpr uint8_t PWM_PIN = 26;
constexpr uint8_t POT_PIN = 34;
constexpr uint8_t BUTTON_PIN = 27;
constexpr uint32_t DEBOUNCE_MS = 30;
constexpr uint32_t SAMPLE_MS = 20;
constexpr uint32_t REPORT_MS = 500;
// Each event is accepted once after 30 ms of stable input.
// If held during reset, a stable release is required before the first press.
struct DebouncedButton {
  bool rawHigh = true;
  bool stableHigh = true;
  bool armed = true;
  bool pressed = false;
  bool released = false;
  uint32_t rawChangedAt = 0;
  uint32_t pressStartedAt = 0;
  void begin(uint32_t now) {
    rawHigh = stableHigh = digitalRead(BUTTON_PIN) == HIGH;
    armed = rawHigh;
    rawChangedAt = now;
    pressed = released = false;
  }
  void update(uint32_t now) {
    pressed = released = false;
    const bool readingHigh = digitalRead(BUTTON_PIN) == HIGH;
    if (readingHigh != rawHigh) {
      rawHigh = readingHigh;
      rawChangedAt = now;
    }
    if (rawHigh != stableHigh && static_cast<uint32_t>(now - rawChangedAt) >= DEBOUNCE_MS) {
      stableHigh = rawHigh;
      if (stableHigh) {
        armed = true;
        released = true;
      } else if (armed) {
        pressed = true;
        pressStartedAt = rawChangedAt;
      }
    }
  }
};
DebouncedButton button;

bool pwmReady = false;
bool playing = false;
uint16_t rawValue = 0;
uint32_t targetFrequency = 200;
uint32_t lastSampleAt = 0;
uint32_t lastReportAt = 0;
uint32_t appliedFrequency = 0;

uint32_t frequencyFromRaw(uint16_t raw) {
  return 200UL + static_cast<uint32_t>(raw) * 1800UL / 4095UL;
}

void stopOnPwmFailure() {
  ledcWriteTone(PWM_PIN, 0);
  ledcDetach(PWM_PIN);
  pinMode(PWM_PIN, OUTPUT);
  digitalWrite(PWM_PIN, LOW);
  pwmReady = false;
  playing = false;
  appliedFrequency = 0;
  Serial.println("PWM ERROR: output disabled; reset to retry.");
}

void setup() {
  Serial.begin(115200);
  pinMode(PWM_PIN, OUTPUT);
  digitalWrite(PWM_PIN, LOW);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  button.begin(millis());
  analogReadResolution(12);
  analogSetPinAttenuation(POT_PIN, ADC_11db);
  rawValue = analogRead(POT_PIN);
  targetFrequency = frequencyFromRaw(rawValue);
  pwmReady = ledcAttach(PWM_PIN, 2000, 10);
  if (!pwmReady) {
    digitalWrite(PWM_PIN, LOW);
    Serial.println("PWM ERROR: ledcAttach failed; output OFF; reset to retry.");
    return;
  }
  ledcWriteTone(PWM_PIN, 0);
  lastSampleAt = lastReportAt = millis();
  Serial.println("Passive piezo: release once after reset, then hold the button to play.");
}

void loop() {
  if (!pwmReady) return;
  const uint32_t now = millis();
  button.update(now);
  if (static_cast<uint32_t>(now - lastSampleAt) >= SAMPLE_MS) {
    lastSampleAt = now;
    rawValue = analogRead(POT_PIN);
    targetFrequency = frequencyFromRaw(rawValue);
  }
  playing = button.armed && !button.stableHigh;
  const uint32_t wantedFrequency = playing ? targetFrequency : 0;
  if (wantedFrequency != appliedFrequency) {
    const uint32_t actualFrequency = ledcWriteTone(PWM_PIN, wantedFrequency);
    if (wantedFrequency != 0 && actualFrequency == 0) {
      stopOnPwmFailure();
      return;
    }
    appliedFrequency = wantedFrequency;
  }
  if (static_cast<uint32_t>(now - lastReportAt) >= REPORT_MS) {
    lastReportAt = now;
    Serial.print("raw="); Serial.print(rawValue);
    Serial.print(" target_Hz="); Serial.print(targetFrequency);
    Serial.print(" playing="); Serial.println(playing ? "YES" : "NO");
  }
}

Pošalji neizmijenjeni program. Nakon pokretanja najprije treba da bude tišina; ton se uključuje tek pravilnim pritiskom tastera.

Od analognog očitavanja do frekvencije

Program očitava potenciometar svakih 20 ms. Postavlja 12-bitnu rezoluciju i ADC_11db za GPIO34. rawValue je vrijednost od 0 do 4095, a frequencyFromRaw() računa 200 + raw × 1800 / 4095. Rezultat se čuva kao targetFrequency.

ADC vrijednostCiljna frekvencija
0200 Hz
1024650 Hz
20481100 Hz
30721550 Hz
40952000 Hz

Cjelobrojno dijeljenje odbacuje decimalni ostatak. Ovo nije kalibrisano mjerenje napona. ADC može dostići maksimum prije krajnjeg položaja potenciometra zbog ograničenog ulaznog opsega; tada dio okretanja više ne mijenja frekvenciju. Opsezi zavise od čipa i opisani su u ADC dokumentaciji.

Ton, taster i početno stanje

ledcAttach(PWM_PIN, 2000, 10) priprema periferiju; konstanta PWM_PIN iznosi 26. Dok je taster stabilno pritisnut, ledcWriteTone() zadaje trenutnu frekvenciju. Frekvencija nula zaustavlja izlaz. Stanje playing opisuje da li program trenutno pušta ton.

Stabilizacija tastera traje 30 ms, pa se i otpuštanje prihvata nakon kratke provjere. Taster zadržan tokom resetovanja mora se prvo otpustiti. Ako inicijalizacija PWM-a ne uspije, pwmReady ostaje false, izlaz je isključen i Serial ispisuje grešku. Neuspjelo zadavanje nenulte frekvencije poziva stopOnPwmFailure(), isključuje izlaz i zahtijeva reset za novi pokušaj. Ton ne treba pokretati direktnim povezivanjem buzzera na GPIO.

Pokretanje i eksperimenti

Drži taster i polako okreći potenciometar. Očekuje se promjena visine tona, uz moguću promjenu njegove glasnoće. Otpusti taster i provjeri da zvuk prestaje. Serial približno svakih 500 ms prikazuje sirovo očitavanje, ciljnu frekvenciju i stanje sviranja.

PostupakOčekivani rezultat
Okreći potenciometar bez pritiskaVrijednosti se mijenjaju, zvuka nema.
Drži taster i polako okrećiTon prati promjenu ciljne frekvencije.
Otpusti tasterNakon stabilizacije ulaza nastupa tišina.
Resetuj sa pritisnutim tasteromNema tona do otpuštanja i novog pritiska.

U bilješke unesi svoja opažanja. Prikazana frekvencija je zadana vrijednost programa, a ne nezavisno izmjerena akustička frekvencija.

Najčešći problemi

ProblemProvjera
Ton ostaje skoro istiProvjeri pasivni piezo tip i mijenja li se rawValue; aktivni buzzer nije odgovarajući dio.
Nema tonaProvjeri B/C/E, napajanje, taster, poruku o PWM grešci i R3/R4 prema šemi.
Ton je slab pri nekim položajimaOdziv stvarnog pretvarača zavisi od frekvencije; provjeri njegov tehnički list.
Frekvencija skačeProvjeri klizač RV1, masu i kontakte; ne ostavljaj analogni ulaz nepovezan.
Maksimum dolazi prije kraja hodaUporedi rawValue sa 4095; moguće je zasićenje ADC-a.

Zadatak i razrađeni odgovori

Promijeni opseg na 400–2400 Hz. Potrebna formula je 400 + raw × 2000 / 4095, jer je širina opsega 2400 − 400 = 2000. Za 0 dobijaš 400 Hz, za 4095 dobijaš 2400 Hz, a za 2048 dobijaš 1400 Hz.

Da li duplo veća frekvencija znači duplo veću glasnoću? Ne; frekvencija određuje visinu, dok glasnoća zavisi od pobude i odziva pretvarača. Zašto postoje i R3 i R4? R3 prazni kapacitivni element, a R4 ograničava impulse kroz tranzistor i smanjuje napon pobude. Zašto se potencijal minusa BZ1 pri isključenju podiže prema 5 V? R3 izjednačava potencijale njegovih priključaka, tako da se napon preko piezo elementa smanjuje prema nuli.

Primarni izvori