📏 سنسور اولتراسونیک HC-SR04 با میکروپایتون روی رزبری پای پیکو (time_pulse_us)
سنسور اولتراسونیک HC-SR04 مثل خفاش کار میکند: یک صدای خیلی زیر (۴۰ کیلوهرتز، بالاتر از شنوایی ما) میفرستد و از روی زمان برگشت پژواک، فاصله را حساب میکند. این سنسور در ربات مسیریاب، سنسور پارک، سطل زبالهی هوشمند و اندازهگیری ارتفاع آب مخزن به کار میرود. در این آموزش آن را با میکروپایتون روی رزبری پای پیکو راه میاندازیم: پالس تریگر میفرستیم، طول پالس Echo را با time_pulse_us اندازه میگیریم، به سانتیمتر تبدیل میکنیم و با یک فیلتر میانه خوانشهای پرت را حذف میکنیم.
HC-SR04 چطور کار میکند؟
- برد یک پالس ۱۰ میکروثانیهای به پایهی TRIG میدهد.
- سنسور هشت موج صوتی ۴۰ کیلوهرتزی میفرستد و پایهی ECHO را بالا (HIGH) میکند.
- وقتی پژواک برمیگردد، ECHO پایین میآید. طول زمانی که ECHO بالا بوده همان زمان رفت و برگشت صداست.
سرعت صوت در هوای ۲۰ درجه حدود ۳۴۳ متر بر ثانیه است، یعنی ۰٫۰۳۴۳ سانتیمتر در هر میکروثانیه. چون صدا رفته و برگشته، فاصله نصف مسیر است:
فاصله (سانتیمتر) = زمان (میکروثانیه) × ۰٫۰۳۴۳ ÷ ۲ — یا تقریباً زمان تقسیم بر ۵۸.
بازهی کاری سنسور از حدود ۲ سانتیمتر تا ۴ متر است. تعریف کوتاهتر را در سنسور اولتراسونیک در واژهنامه ببین.
قطعهها
- رزبری پای پیکو
- سنسور اولتراسونیک HC-SR04
- یک مقاومت ۱ کیلواهم و یک مقاومت ۲ کیلواهم (یا دو تا ۱ کیلو سری) برای تقسیم ولتاژ Echo
سیمکشی و مسئلهی ۵ ولت
HC-SR04 معمولی با ۵ ولت کار میکند و پایهی ECHO آن هم ۵ ولت بیرون میدهد. پایههای پیکو ۳٫۳ ولتیاند، پس Echo را با یک تقسیم ولتاژ پایین میآوریم: ۵ × ۲ ÷ (۱ + ۲) ≈ ۳٫۳ ولت.
| پایهی سنسور | اتصال |
|---|---|
| VCC | VBUS پیکو (پایهی فیزیکی ۴۰، پنج ولت USB) |
| GND | GND پیکو |
| TRIG | مستقیم به GP15 (پایهی فیزیکی ۲۰) |
| ECHO | به مقاومت ۱ کیلو؛ سر دیگر آن به GP14 (پایهی ۱۹) |
| نقطهی GP14 | از راه مقاومت ۲ کیلو به GND |
برای حساب مقاومتهای دیگر ماشینحساب تقسیم ولتاژ را ببین. اگر مدل HC-SR04P یا RCWL-1601 داری که با ۳٫۳ ولت هم کار میکند، VCC را به 3V3(OUT) بزن و تقسیم ولتاژ لازم نیست.
کد کامل میکروپایتون
from machine import Pin, time_pulse_us
import time
trig = Pin(15, Pin.OUT)
echo = Pin(14, Pin.IN)
led = Pin("LED", Pin.OUT) # on-board LED as a "too close" warning
SOUND_CM_PER_US = 0.0343 # speed of sound at about 20 C
TIMEOUT_US = 30000 # 30 ms, about 5 m round trip
def distance_cm():
trig.value(0)
time.sleep_us(2)
trig.value(1)
time.sleep_us(10) # the 10 us trigger pulse
trig.value(0)
duration = time_pulse_us(echo, 1, TIMEOUT_US)
if duration < 0: # -1 or -2: timeout, nothing measured
return None
return duration * SOUND_CM_PER_US / 2
def median_distance(n=5):
values = []
for i in range(n):
d = distance_cm()
if d is not None:
values.append(d)
time.sleep_ms(60) # let old echoes die out
if not values:
return None
values.sort()
return values[len(values) // 2]
while True:
d = median_distance()
if d is None:
print("out of range")
led.off()
else:
print(f"distance: {d:.1f} cm")
led.value(d < 20) # LED on when closer than 20 cm
time.sleep_ms(100)
توضیح خط به خط
from machine import Pin, time_pulse_us:time_pulse_usمعادلpulseInآردوینو است و در ماژولmachineقرار دارد، نهtime.- پالس تریگر: اول ۲ میکروثانیه پایین تا شروع تمیز باشد، بعد ۱۰ میکروثانیه بالا و دوباره پایین.
time.sleep_usبرای این زمانهای کوتاه است. time_pulse_us(echo, 1, TIMEOUT_US): صبر میکند تا Echo بالا برود، بعد زمان بالا ماندنش را بر حسب میکروثانیه برمیگرداند. عدد ۱ یعنی «پالس بالا را اندازه بگیر».- timeout: پیشفرض این تابع یک ثانیه است؛ یعنی اگر جلوی سنسور خالی باشد، برنامه یک ثانیه گیر میکند. ۳۰ میلیثانیه برای ۴ تا ۵ متر کافی است و برنامه را چابک نگه میدارد.
- عدد منفی: ۲- یعنی پالس هیچوقت شروع نشد و ۱- یعنی شروع شد ولی تمام نشد. هر دو را «خارج از برد» حساب میکنیم و
Noneبرمیگردانیم. - فیلتر میانه: گاهی سنسور به خاطر پژواک کج یا سطح نرم یک عدد پرت میدهد. پنج خوانش میگیریم، مرتب میکنیم و وسطی را برمیداریم؛ عدد پرت خودبهخود کنار میرود. میانگین این کار را نمیکند، چون یک عدد خیلی بزرگ کل میانگین را خراب میکند.
time.sleep_ms(60): بین دو اندازهگیری صبر کن تا پژواک قبلی کاملاً خاموش شود؛ وگرنه اندازهی بعدی پژواک قدیمی را میگیرد.led.value(d < 20): حاصل مقایسه True یا False است و مستقیم LED را روشن یا خاموش میکند.
اجرا در شبیهساز: صادقانه
پیکوی شبیهساز تینکرکد فارسی تابع time_pulse_us را ندارد، پس خواندن خود HC-SR04 با میکروپایتون را روی برد واقعی امتحان کن. دو راه برای تمرین بدون برد داری:
- خود سنسور، رایگان، با آردوینو: HC-SR04 در حالت آردوینو جزو قطعههای شبیهساز است و آردوینو Uno رایگان است. پروژهی آمادهی فاصلهسنج و درس سنسور فاصله همین منطق را با
pulseInنشان میدهند؛ نسخهی کاملترش در سنسور اولتراسونیک با آردوینو آمده. - منطق برنامه روی پیکوی مجازی: تابع
distance_cmرا موقتاً با یک پتانسیومتر روی GP26 عوض کن و بقیهی برنامه (فیلتر، آستانه، LED) را تمرین کن. پیکو و میکروپایتون جزو اشتراک پلاس هستند.
from machine import Pin, ADC
import time
knob = ADC(26) # stands in for the sensor while practising
led = Pin("LED", Pin.OUT)
def distance_cm():
# 0..65535 from the knob -> 2..400 cm, like the real sensor's range
return 2 + knob.read_u16() * 398 / 65535
while True:
d = distance_cm()
print(f"distance: {d:.1f} cm")
led.value(d < 20)
time.sleep_ms(200)
وقتی برد واقعی رسید، فقط تابع distance_cm را با نسخهی time_pulse_us عوض کن؛ بقیهی برنامه دست نمیخورد.
اشکالهای رایج
- همیشه out of range: TRIG و ECHO را جابهجا وصل کردهای، یا سنسور برق ۵ ولت ندارد (VBUS فقط با USB برق دارد).
- عدد همیشه حدود صفر یا خیلی کوچک: شیء از ۲ سانتیمتر نزدیکتر است، یا سنسور خودش را از لبهی میز «میبیند». سنسور را بالاتر و صاف بگذار.
- عددها میپرند: سطح نرم (پارچه، اسفنج) یا کج صدا را جذب یا منحرف میکند. فیلتر میانه را با ۷ یا ۹ خوانش امتحان کن.
- برنامه هر بار یک ثانیه گیر میکند: آرگومان timeout را به
time_pulse_usندادهای. - ImportError روی time_pulse_us: آن را از
machineوارد کن، نه ازtime. - Echo بدون تقسیم ولتاژ: ممکن است مدتی کار کند، ولی پایهی پیکو را آهسته آسیب میزند. مقاومتها را جا نینداز.
ایدههای بعدی: سنسور را روی یک سروو بگذار و یک رادار بساز، یا با بازر یک سنسور دندهعقب درست کن. نسخهی کامل یک پروژهی واقعی با اولتراسونیک را در پارکینگ هوشمند با آردوینو ببین. برای پیدا کردن پایهها پین اوت رزبری پای پیکو و برای همهی امکانات برد صفحهی رزبری پای پیکو را ببین.
فاصلهسنج اولتراسونیک را رایگان امتحان کن 📏سؤالهای رایج
آیا HC-SR04 را میشود مستقیم به پیکو وصل کرد؟
TRIG را بله، چون ۳٫۳ ولت پیکو برای تریگر کافی است. ولی خروجی ECHO در مدل معمولی ۵ ولت است و پایهی ۳٫۳ ولتی پیکو را تهدید میکند. با دو مقاومت ۱ و ۲ کیلواهم ولتاژ Echo را به حدود ۳٫۳ ولت برسان، یا مدل HC-SR04P را بگیر که با ۳٫۳ ولت کار میکند.
time_pulse_us چه عددی برمیگرداند؟
طول پالس بر حسب میکروثانیه. اگر تا پایان زمان timeout پالسی شروع نشود ۲- و اگر پالس شروع شود ولی تمام نشود ۱- برمیگرداند. پس هر عدد منفی یعنی «چیزی اندازه گرفته نشد».
این کد در شبیهساز اجرا میشود؟
پیکوی شبیهساز تینکرکد فارسی تابع time_pulse_us را ندارد، پس خواندن خود HC-SR04 با میکروپایتون را روی برد واقعی امتحان کن. مثال آمادهی فاصلهسنج با آردوینو در شبیهساز رایگان است، و بقیهی منطق برنامه را میتوانی روی پیکوی مجازی با یک پتانسیومتر به جای سنسور تمرین کنی.
مقالههای مرتبط
راهاندازی LCD I2C با میکروپایتون روی رزبری پای پیکو (درایور i2c_lcd)
سنسور دما و رطوبت DHT11 و DHT22 با میکروپایتون روی رزبری پای پیکو
Timer در میکروپایتون: چند کار همزمان روی رزبری پای پیکو بدون sleep
سنسور نور LDR (فتوسل) با آردوینو: مقسم ولتاژ، کد کامل و چراغ خواب خودکار
همهی آموزشهای رزبری پای پیکو و میکروپایتون ← · همهی مقالهها