7.3 Senzor za parkiranje
Ovaj projekt gradi senzor za parkiranje pri vožnji natraške koji već poznaješ iz automobila. Ultrazvučni senzor promatra prostor pred sobom, i što nešto dođe bliže, to buzzer piska brže. Priđi unutar 10 cm i piskanje se stopi u jedan neprekinut ton, a upali se svjetlo upozorenja.
To je prvi projekt koji na pločicu stavlja Qwiic modul i krug na breadboardu u isto vrijeme. Senzor dolazi na jednom kabelu, točno kao u sekciji 3.1, dok su buzzer iz sekcije 2.4 i LED-ica iz sekcije 3.2 spojeni ručno. Dva izlaza, jedan senzor, i mali dio logike vremena koji ih spaja.
U ovoj dokumentaciji naučit ćeš:
- Kako pobuđivati dva različita izlaza iz jedne jedine vrijednosti senzora.
- Kako nešto natjerati da se događa odabranom brzinom bez korištenja
delay(), tako da mjerenje nikada ne prestaje. - Zašto skica pretvara odgovor senzora prije nego ga usporedi s bilo čim.
- Što je slijepa zona senzora, i zašto zbog nje ovaj projekt utihne kada priđeš previše blizu.
- Kako lanac
if/else ifjedan broj pretvara u pet različitih ponašanja.
Potreban hardver:
- 1x Soldered NULA MINI pločica
- 1x Breadboard
- 1x Ultrazvučni senzor udaljenosti (Qwiic)
- 1x Qwiic kabel
- 1x Pasivni buzzer
- 1x LED-ica (bilo koje boje)
- 1x otpornik od 330 Ω (narančasti-narančasti-smeđi)
- 5x Jumper žice
- 1x USB-C kabel
Spajanje komponenti
Oba pina koje ovaj projekt koristi su na f–j strani pločice: IO2 u redu 25 za buzzer, i IO5 u redu 28 za LED-icu. Tijelo pločice prekriva stupce f–i, pa su j25, j28 i j30 rupice u koje stvarno možeš uvesti žicu. Sve ostalo odvija se dalje duž iste f–j strane, dobro odmaknuto od pločice.
IO5 na f–j strani i IO18 na a–e strani, a red 25 je IO2 na f–j strani ali TX na a–e strani. Broji redove na istoj strani na koju utiskuješ.1. Umetni NULA MINI pločicu na breadboard
Utisni pločicu u jedan kraj breadboarda tako da njezina dva reda pinova sjednu s obje strane središnjeg kanala, s čipom okrenutim prema dolje.

2. Postavi buzzer i spoji ga na IO2
U ovom koraku događaju se tri stvari, jer pripadaju zajedno.
Prvo povuci jumper žicu iz j30 (GND) do plave − vodilice. Ta vodilica postaje dijeljena linija mase za sve ostalo u projektu.
Zatim utisni buzzer u f–j stranu s njegove dvije nožice u redu 15 i redu 14. Pogledaj vrh njegovog kućišta prije toga: uz oznaku HWDZ nalazi se mali + unutar kružića, i nožica na toj strani je pozitivna. Ta nožica ide u red 15.
Na kraju, jedna jumper žica iz j15 u j25 (IO2) da nosi zvuk, i jedna iz j14 do plave − vodilice da zatvori krug.

3. Izvedi IO5 do LED-ice i dodaj otpornik
Jedna jumper žica iz j28 (IO5) duž do j8. To je žica koja će uključivati svjetlo upozorenja.
Zatim otpornik od 330 Ω iz i8 u i6, premošćujući ta dva reda. Prstenovi mu se čitaju narančasti-narančasti-smeđi.

4. Dodaj LED-icu
LED-ica ide unutra s dugom nožicom u redu 6, redu koji otpornik napaja, i s kratkom nožicom u redu 5.

5. Spoji LED-icu na masu
Još jedna jumper žica, iz j5 (red u kojem je kratka nožica LED-ice) do plave − vodilice.

Lanac je sada zatvoren od kraja do kraja: IO5 → otpornik → LED-ica → GND.
6. Utisni ultrazvučni senzor
Senzoru ne trebaju rupice breadboarda uopće. To je Qwiic modul, pa jedan kabel nosi njegovo napajanje i njegove podatke zajedno, i ulazi samo na jedan način.
Utisni jedan kraj u Qwiic konektor pločice, onaj bijeli na rubu između tipki USER i RST, a drugi u bilo koji konektor na ljubičastoj ULTRASONIC SENSOR QWIIC pločici. Ima ih dva, po jedan na svakom kraju, spojena međusobno, pa nije važno koji odabereš.

Ako želiš vidjeti točno o kojem se konektoru radi na goloj pločici, ovdje je istaknut:

ON. On postavlja adresu na koju senzor odgovara, a kod očekuje tvorničku postavku.7. Spoji pločicu na računalo
Okreni senzor tako da njegova dva srebrna pretvarača gledaju u prostoriju, drži prostor pred njima čistim, i utisni USB-C kabel.

Kako jedan broj postaje pet ponašanja
Sve što ovaj projekt radi dolazi iz jednog jedinog mjerenja, provučenog kroz lanac if i else if:
| Udaljenost | Buzzer | LED-ica |
|---|---|---|
| više od 100 cm | tih | ugašena |
| 60–100 cm | polagano piskanje, 800 ms razmaka | ugašena |
| 30–60 cm | srednje piskanje, 400 ms razmaka | ugašena |
| 10–30 cm | brzo piskanje, 150 ms razmaka | ugašena |
| manje od 10 cm | jedan neprekinut ton | upaljena |
Pločica te raspone provjerava od najšireg prema dolje i zaustavlja se na prvom koji se poklopi, i zato svaka provjera treba samo donju granicu. Kada dođe do else if (distance > 30), sve iznad 60 već je obrađeno.
Piskanje bez zaustavljanja programa
Očit način da se napravi pisak je tone(), delay(), noTone(), delay(). Ova skica to ne radi, a razlog vrijedi razumjeti, jer je to jedna od najkorisnijih ideja u cijelom kitu.
delay() ne znači "čekaj u pozadini". Znači stani. Tijekom delay(800) pločica ne radi ništa drugo uopće. Ne može mjeriti, ne može primijetiti da se približavaš, ne može reagirati. Senzor za parkiranje koji prestane gledati na osam desetinki sekunde odjednom nije baš senzor za parkiranje.
Zato skica umjesto toga vodi zapis o vremenu:
unsigned long lastBeep = 0;
unsigned long beepInterval = 0;
bool buzzerOn = false;
millis() vraća koliko milisekundi pločica radi. U svakom prolazu kroz petlju skica od trenutka sada oduzima trenutak posljednje promjene, i djeluje samo kada je prošlo dovoljno vremena:
if (now - lastBeep >= beepInterval) {
lastBeep = now;
buzzerOn = !buzzerOn;
if (buzzerOn) tone(BUZZER_PIN, TONE_FREQ);
else noTone(BUZZER_PIN);
}
Operator ! preokreće true u false i natrag, pa svaki put kada interval istekne buzzer se prebaci na obrnuto od onoga što je bio. Uključen, isključen, uključen, isključen: to iznova i iznova je ono što čuješ kao piskanje. Manji beepInterval znači manje čekanja između prebacivanja, a to je brže piskanje.
Čitanje senzora, i ispravno čitanje
Tri detalja u kodu zaslužuju bliži pogled.
Ide u dva poziva, ne u jedan
hc.takeMeasure();
delay(MEASURE_WAIT_MS);
uint16_t reading = hc.getDistance();
takeMeasure() samo traži od senzora da ode i obavi posao. Senzoru zatim treba trenutak (odustaje od slušanja nakon oko 38 milisekundi ako odjek ne dođe), pa skica čeka 50 ms prije nego getDistance() pokupi gotov odgovor. To je u cijelosti objašnjeno u 3.1 Mjerenje udaljenosti.
To čekanje od 50 ms također je i jedina pauza u cijeloj petlji, i zato na njezinom dnu nema delay(). Mjerenje postavlja tempo: oko dvadeset vrijednosti u sekundi.
Odgovor dolazi u milimetrima
int distance = reading / 10;
Senzor prijavljuje udaljenost u milimetrima, pa vrijednost 250 znači 25 centimetara. Svaki prag dalje u skici napisan je u centimetrima, jer bi tako osoba opisala udaljenost, pa se vrijednost ovdje pretvori jednom, a pretvorena vrijednost je ono s čime lanac if uspoređuje.
distance > 100 značio bi 10 cm a ne 1 m, i cijeli senzor za parkiranje na kraju bi radio samo unutar mjehurića od 10 cm. Kad god koristiš novi senzor, provjeri u kojoj jedinici odgovara prije nego ga usporediš s bilo čim.Nula nije udaljenost
if (reading == 0) {
Serial.println("No echo received, nothing in range.");
...
return;
}
Senzor odgovara 0 kad god nije čuo odjek koji može upotrijebiti, a to se događa u dvije suprotne situacije: kada ništa nije u dosegu, i kada je nešto bliže od oko 3 centimetra.
Druga ljude iznenađuje. Svaki ultrazvučni senzor ima slijepu zonu neposredno pred sobom. Senzor odašilje prasak zvuka i onda sluša da se vrati, ali se s vrlo blizu odjek vrati prije nego je prasak završio, pa dolazi dok senzor još govori i nikada ga ne čuje.
Nijedan slučaj nije pravo mjerenje. Kada bi skica 0 tretirala kao udaljenost, čitalo bi se kao "nula centimetara daleko" i pokretalo bi alarm punom snagom kad god je put slobodan, pa umjesto toga utihne i čeka sljedeću vrijednost.
Kod
/**
**************************************************
*
* @file 7.3_Parking_sensor.ino
* @brief Projekt koji gradi senzor za parkiranje kakav poznaješ iz automobila. Soldered ultrazvučni senzor udaljenosti
* pazi na prepreke, i što jedna dođe bliže, to buzzer piska brže. Pod 10 cm piskanje
* prelazi u jedan neprekinut ton a LED-ica se upali kao konačno upozorenje.
* Gradi se na mjerenju udaljenosti iz sekcije 3.1 i buzzeru iz sekcije 2.4.
* Za detalje, shemu spajanja i više, pogledaj dokumentaciju primjera na: <link placeholder>
* @author Soldered
***************************************************
*/
/*
Uključi Soldered biblioteku za ultrazvučni senzor udaljenosti, da udaljenost možemo pročitati jednim pozivom
funkcije umjesto da sami mjerimo vrijeme odjeka.
*/
#include "Ultrasonic-distance-sensor-easyC-SOLDERED.h"
/*
Ovo je varijabla kojoj predajemo broj pina na koji smo spojili buzzer.
NULA pločica ima logiku imenovanja pinova ovako: IO2, gdje je 2 broj koji dajemo varijabli.
*/
const int BUZZER_PIN = 2;
/*
Ovo je varijabla kojoj predajemo broj pina na koji smo spojili LED-icu upozorenja.
Zapamti da LED-ici treba otpornik od 330 ohma u seriji s njom. Taj otpornik ograničava koliko struje teče, a
bez njega LED-ica vuče više nego što su ona ili pin građeni izdržati, pa se oboje može oštetiti.
*/
const int LED_PIN = 5;
/*
Ovdje stvaramo naš objekt senzora, koji smo nazvali "hc". Senzor se spaja preko easyC-a, a to je Soldered ime za
I2C vezu preko jednog kabela, pa ne predajemo nikakve brojeve pinova: I2C uvijek koristi ista dva pina na pločici (IO6 i
IO7 na NULA pločici) a biblioteka već zna da tamo gleda.
*/
Ultrasonic_Sensor hc;
/*
Ovoliko čekamo nakon što zatražimo mjerenje, u milisekundama. Senzor odustaje od slušanja odjeka
nakon 38 milisekundi, pa čekanje malo dulje od toga znači da je odgovor uvijek gotov kada za njega pitamo.
To čekanje također postavlja tempo cijele petlje, i zato na njezinom dnu nema delay().
*/
const int MEASURE_WAIT_MS = 50;
/*
Ovo je frekvencija zvuka upozorenja, u hercima. Frekvencija je koliko se puta u sekundi buzzer pomakne naprijed
i natrag, a naše uho to čuje kao visinu zvuka. Mali buzzeri kao ovaj najglasniji su negdje između
2 i 4 kHz, pa slobodno eksperimentiraj s ovom vrijednošću dok ti ne zvuči najbolje.
*/
const int TONE_FREQ = 2700;
/*
Ove tri varijable su ono što nam dopušta piskanje različitim brzinama a da program nikada ne zaustavimo.
"lastBeep" pamti trenutak kada je buzzer posljednji put uključen ili isključen, "beepInterval" drži koliko želimo čekati
između tih prebacivanja, a "buzzerOn" pamti oglašava li se buzzer trenutno ili je tih.
*/
unsigned long lastBeep = 0;
unsigned long beepInterval = 0;
bool buzzerOn = false;
void setup()
{
/*
Serial.begin() uspostavlja serijsku komunikaciju između tvoje pločice i tvog računala preko USB kabela. Ovdje ga koristimo
da gledamo izmjerenu udaljenost dok testiramo senzor.
*/
Serial.begin(115200);
/*
begin() priprema senzor za upotrebu. Za easyC senzor to pokreće I2C komunikaciju i govori biblioteci na koju
adresu da se obraća, a za ovaj senzor je to 0x30.
*/
hc.begin();
/*
pinMode() je funkcija koja konfigurira zadani pin da se ponaša ili kao ulaz ili u ovom slučaju kao izlaz.
I buzzer i LED-ica su stvari u koje pišemo, pa oba idu u OUTPUT mod. Odmah nakon toga u pin LED-ice pišemo LOW
da svjetlo upozorenja počne ugašeno.
*/
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
//Ispiši početnu poruku da znamo da se program uspješno pokrenuo.
Serial.println("Ultrasonic buzzer + LED reverse sensor started");
}
void loop()
{
/*
Čitanje easyC senzora ide u dva koraka. takeMeasure() traži od senzora da pošalje puls i izmjeri vrijeme odjeka, a
čekanje nakon toga daje mu trenutak koji mu treba da taj posao dovrši i spremi odgovor.
*/
hc.takeMeasure();
delay(MEASURE_WAIT_MS);
/*
getDistance() zatim dohvaća spremljeni odgovor. Primijeti jedinicu: senzor prijavljuje udaljenost u MILIMETRIMA, pa
vrijednost 250 znači da je prepreka 25 centimetara daleko. Držimo je u varijabli imena "reading" da nas ime
podsjeti da to još nije jedinica u kojoj želimo razmišljati.
*/
uint16_t reading = hc.getDistance();
/*
Senzor odgovara s 0 kad god nije čuo odjek koji može upotrijebiti. To se događa u dvije suprotne situacije: kada
ništa nije u dosegu, i kada je objekt bliže od oko 3 centimetra, jer se tada odjek vrati
prije nego je senzor završio odašiljanje i on ga nikada ne čuje. Nijedno nije pravo mjerenje, a tretiranje jednog kao
udaljenosti pokretalo bi alarm kad god je put slobodan, pa umjesto toga utihnemo i čekamo sljedeću.
*/
if (reading == 0) {
Serial.println("No echo received, nothing in range.");
noTone(BUZZER_PIN);
buzzerOn = false;
digitalWrite(LED_PIN, LOW);
return;
}
/*
Sada vrijednost pretvaramo u centimetre, jer bismo tako prirodno opisali udaljenost osobi, i tako je
napisan svaki broj dalje u ovoj skici. Deset milimetara čini jedan centimetar, pa dijelimo s deset. To je
cjelobrojno dijeljenje, pa 253 milimetra postaje 25 centimetara, a to je i sva točnost koju ovaj senzor
iskreno može ponuditi.
*/
int distance = reading / 10;
//Ispiši izmjerenu udaljenost u Serial Monitor da možemo pratiti dok testiramo.
Serial.print("Distance from obstacle: ");
Serial.print(distance);
Serial.println(" cm");
/*
LED-icu gasimo na početku svakog prolaza kroz petlju. Samo je najbliži raspon nekoliko linija ispod ponovno
pali, pa nas ta jedna linija poštedi toga da je gasimo u svakom drugom slučaju.
*/
digitalWrite(LED_PIN, LOW);
/*
Ovaj lanac if izjava je srce projekta: pretvara udaljenost u brzinu piskanja. Svaki raspon dobiva
drugačiju vrijednost beepInterval, a manji interval znači manje čekanja između pisaka, što čujemo kao brže
piskanje. Pločica raspone provjerava od najšireg prema dolje i zaustavlja se na prvom koji se poklopi.
Slobodno eksperimentiraj i s udaljenostima i s intervalima.
*/
if (distance > 100) {
//Ništa u dosegu. noTone() zaustavlja svaki zvuk koji je buzzer pravio a interval od 0 drži ga tihim.
beepInterval = 0;
noTone(BUZZER_PIN);
}
else if (distance > 60) {
//Između 60 i 100 cm, piskaj polagano.
beepInterval = 800;
}
else if (distance > 30) {
//Između 30 i 60 cm, piskaj srednjom brzinom.
beepInterval = 400;
}
else if (distance > 10) {
//Između 10 i 30 cm, piskaj brzo.
beepInterval = 150;
}
else {
/*
Bliže od 10 cm. Ovdje pozivamo tone() bez intervala, što buzzer tjera da se oglašava neprekidno umjesto da
piska, i palimo LED-icu kao konačno upozorenje.
*/
tone(BUZZER_PIN, TONE_FREQ);
beepInterval = 0;
digitalWrite(LED_PIN, HIGH);
}
/*
Ovdje se samo piskanje događa. millis() je funkcija koja vraća broj milisekundi koje su prošle
od kada je pločica počela izvršavati trenutni program. Usporedbom s trenutkom posljednjeg prebacivanja možemo čekati
pravu količinu vremena bez korištenja delay(), koji bi zamrznuo program i zaustavio nas u mjerenju.
Svaki put kada interval prođe, buzzerOn preokrenemo u obrnutu vrijednost operatorom "!", pa onda ili
pokrenemo ton ili ga zaustavimo. To iznova i iznova je ono što proizvodi pisak.
*/
if (beepInterval > 0) {
unsigned long now = millis();
if (now - lastBeep >= beepInterval) {
lastBeep = now;
buzzerOn = !buzzerOn;
if (buzzerOn) tone(BUZZER_PIN, TONE_FREQ);
else noTone(BUZZER_PIN);
}
}
}
Što bi trebao vidjeti
Otvori Serial Monitor na 115200 bauda. Nakon ROM boot poruka, skica se najavljuje:
Ultrasonic buzzer + LED reverse sensor started
ESP-ROM:esp32c6-..., SPIWP, load: i entry ispisuje ugrađeni bootloader čipa pri svakom resetu, prije nego se tvoj program pokrene. Izgledaju uznemirujuće a znače da ništa nije u krivu.Od tada dobivaš liniju oko dvadeset puta u sekundi. Pomiči ruku polako prema senzoru i gledaj kako brojevi padaju:
To jedno izvođenje prolazi kroz cijeli projekt. Vrijednosti počinju oko 26 cm, a to je brzo piskanje. Prelaze 10 cm oko trećine niz ispis, i od tamo piskanje prestaje i drži jedan neprekinut ton, a svjetlo upozorenja se upali.
12 cm na 25 cm i odmah natrag na 10 cm. Ta zalutala vrijednost je normalna. Ultrazvučni senzor ponekad ulovi odjek s tvog rukava, stola ili ruba ruke umjesto s njezine ravnine. Ovdje to nije važno, jer druga vrijednost dolazi 50 milisekundi kasnije. To vrijedi zapamtiti kad god koristiš senzor udaljenosti: sudi ga po nizu vrijednosti, nikada po jednoj.Unutar 10 cm pločica izgleda ovako:

Kada pred senzorom nema ničega, ili kada je nešto priljubljeno uz njega, umjesto toga dobiješ ovo:
No echo received, nothing in range.
Ako ton nikada ne postane neprekinut, ili nisi dovoljno blizu, ili si previše blizu. Zapamti slijepu zonu: objekt koji dotiče pretvarače tjera senzor da prestane odgovarati, i sve utihne. Oko 5 cm je zlatna sredina.
Ako ton postane neprekinut ali LED-ica ostane tamna, kod radi svoj posao a greška je u krugu. Provjeri prvo je li LED-ica postavljena na pravu stranu: duga nožica pripada u red 6, okrenuta prema otporniku.
Cijeli primjer
Pogledaj cijeli kod primjera na linku ispod:
7.3_Parking_sensor.ino
Projekt koji pomoću ultrazvučnog senzora, buzzera i LED-ice simulira sustav upozorenja pri parkiranju natraške.