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
| Komponenta | Količina | Specifikacija i napomene |
|---|---|---|
| ESP32 razvojna ploča sa klasičnim ESP32-WROOM-32 modulom | 1 | GPIO nazivi moraju odgovarati referentnom profilu; fizički položaj izvoda provjeriti na ploči. |
| USB kabl za podatke i napajanje | 1 | Priključak prilagoditi ploči; komplet na slici navodi Micro-USB. |
| Eksperimentalna ploča | 1 | Komplet navodi 830 kontaktnih tačaka. Provjeriti eventualni prekid naponskih vodova. |
| Pasivni buzzer — referentni piezo element | 1 | Fotografija navodi pasivni buzzer, ne njegov tip. Ova šema zahtijeva piezo za pobudu 0–5 V; magnetni pretvarač zahtijeva zasebno usklađivanje. |
| Dodatni NPN tranzistor PN2222A | 1Obavezno dodatno — nije na slici kompleta | DODATNO, 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 1N4148 | 1Obavezno dodatno — nije na slici kompleta | DODATNO, 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Ω | 2 | Otpornik baze; u kursu 14 i paralelni otpornik piezo elementa. Količina ove vrijednosti u kompletu nije potvrđena. |
| Otpornik 10 kΩ | 1 | R2 je pull-down od baze Q1 prema GND; baza ostaje nisko dok GPIO ne upravlja. |
| Otpornik 220 Ω | 1 | R4 je serijski otpornik između BZ1.MINUS i Q1.C; ograničava impuls punjenja piezo elementa. |
| Trenutni taster | 1 | Koristiti par priključaka koji se spaja pritiskom; ista strana četvoronožnog tastera može već biti spojena. |
| Potenciometar 10 kΩ | 1 | Dva krajnja izvoda i klizač W; raspored utvrditi prema stvarnoj komponenti. |
| Spojni kablovi | 13 | M-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.
| Od | Do | Opis veze |
|---|---|---|
ESP32.GPIO26 | R1.1 | Otpornik R1 od 1 kΩ ograničava struju baze. |
R1.2 | Q1.B | Baza dodatnog PN2222A tranzistora. |
Q1.B | R2.1 | R2 od 10 kΩ drži bazu nisko dok GPIO ne upravlja. |
R2.2 | ESP32.GND | Drugi kraj pull-down otpornika. |
Q1.E | ESP32.GND | Emiter prema zajedničkoj masi; provjeriti stvarni B/C/E raspored. |
ESP32.USB5V | BZ1.PLUS | Provjereni USB vod 5 V prema pozitivnom izvodu buzzera. |
D1.K | ESP32.USB5V | Katoda zaštitne 1N4148, označena prstenom, prema +5 V. |
BZ1.MINUS | R4.1 | R4 od 220 Ω je između piezo sklopa i kolektora; ograničava impuls punjenja. |
R4.2 | Q1.C | Drugi kraj serijskog R4 prema kolektoru. |
D1.A | BZ1.MINUS | Anoda diode na MINUS strani piezo elementa, prije R4. |
BZ1.PLUS | R3.1 | R3 od 1 kΩ je paralelno piezo elementu. |
R3.2 | BZ1.MINUS | R3 zatvara put pražnjenja između PLUS i MINUS. |
ESP32.GPIO27 | SW1.CONTACT_A | Taster na ulaz sa INPUT_PULLUP. |
SW1.CONTACT_B | ESP32.GND | Drugi izvod odabranog para kontakata, koji se spaja pritiskom. |
ESP32.3V3 | RV1.END_A | Jedan krajnji izvod potenciometra 10 kΩ. |
ESP32.GND | RV1.END_B | Drugi krajnji izvod. |
RV1.W | ESP32.GPIO34 | Klizač 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
- Isključi USB. Spoji GND ploče, emiter Q1 i zajedničku masu.
- Poveži GPIO26 preko R1 od 1 kΩ sa bazom. Dodaj R2 od 10 kΩ između baze i mase.
- Poveži plus BZ1 na USB 5 V. Označi čvor na njegovom minusu kao X.
- Poveži R3 od 1 kΩ između plusa BZ1 i čvora X: on je paralelan sa piezo elementom.
- Spoji čvor X preko R4 od 220 Ω na kolektor Q1. Ovdje nema direktne žice od minusa BZ1 do kolektora.
- Dodaj D1: anoda na X, katoda sa prstenom na plus/5 V. Dioda ostaje neposredno preko BZ1, prije R4.
- Spoji krajnje izvode RV1 od 10 kΩ na 3V3 i GND, a klizač na GPIO34.
- 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
#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 vrijednost | Ciljna frekvencija |
|---|---|
| 0 | 200 Hz |
| 1024 | 650 Hz |
| 2048 | 1100 Hz |
| 3072 | 1550 Hz |
| 4095 | 2000 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.
| Postupak | Očekivani rezultat |
|---|---|
| Okreći potenciometar bez pritiska | Vrijednosti se mijenjaju, zvuka nema. |
| Drži taster i polako okreći | Ton prati promjenu ciljne frekvencije. |
| Otpusti taster | Nakon stabilizacije ulaza nastupa tišina. |
| Resetuj sa pritisnutim tasterom | Nema 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
| Problem | Provjera |
|---|---|
| Ton ostaje skoro isti | Provjeri pasivni piezo tip i mijenja li se rawValue; aktivni buzzer nije odgovarajući dio. |
| Nema tona | Provjeri B/C/E, napajanje, taster, poruku o PWM grešci i R3/R4 prema šemi. |
| Ton je slab pri nekim položajima | Odziv stvarnog pretvarača zavisi od frekvencije; provjeri njegov tehnički list. |
| Frekvencija skače | Provjeri klizač RV1, masu i kontakte; ne ostavljaj analogni ulaz nepovezan. |
| Maksimum dolazi prije kraja hoda | Uporedi 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.
