فاصلهسنجی • HC-SR04 • ESP32 / Arduino
در این پروژه یک فاصلهسنج رومیزی میسازیم که علاوه بر عدد، معتبر بودن اندازهگیری را گزارش میکند. HC-SR04 برای یادگیری زمانسنجی و آزمایش فاصله تا یک هدف مناسب است؛ اما داشتن یک عدد در سریال، صحت اندازهگیری یا ایمنی سامانه را ثابت نمیکند. از اتصال امن Echo شروع میکنیم، زمان پالس را میخوانیم و سپس فیلتر ساده و مقایسه با VL53L0X را بررسی میکنیم.

اندازهگیری روی میز، ثبت تغییر فاصله یک صفحه و تمرین تشخیص نزدیکشدن مانع، نقطه شروعهای خوبی هستند. در بررسی امروز، ECA این مدل را موجود نشان داد؛ تجربه دارای نشان خریدار درباره کار با ماژول و مشکل خواندن صفر در نبود بازتاب نیز دیده شد. این شواهد از استفاده عملی حکایت میکنند، نه آمار فروش یا تضمین مشتری. صفحه همان مدل در آفتاب رایانه هم بررسی شد، ولی ناموجود بود.
این آموزش مدار ایمنی خودرو، جلوگیری تضمینی از برخورد یا کنترل خودکار پمپ نیست. نخست فقط گزارش سریال را آزمایش کنید؛ یک قرائت نامعتبر نباید فرمان حرکت یا روشنشدن بار ایجاد کند.
در رابط معمول Trig/Echo، میکروکنترلر یک پالس تحریک میفرستد. ماژول موج صوتی ارسال میکند و مدت پالس Echo نماینده زمان رفتوبرگشت است. رابطه آموزشی ما d = t × c / 2 است؛ تقسیم بر دو مسیر برگشت را حذف میکند.
با فرض سرعت ۳۴۰ متر بر ثانیه، ضریب تبدیل برابر 0.034 cm/µs میشود. مثلاً پالس فرضی ۱۰۰۰ میکروثانیه، در همین مدل محاسباتی ۱۷ سانتیمتر میدهد. این مثال حسابی است، نه نتیجه آزمایش سختافزاری. ضریب ثابت، تغییر شرایط هوا را جبران نمیکند.
| مورد | مرجع HC-SR04 معمولی | برداشت کاربردی |
|---|---|---|
| تغذیه | ۵ ولت DC | تغذیه و سطح منطقی Echo را جدا بررسی کنید. |
| پالس Trig | حداقل ۱۰ میکروثانیه HIGH | کد یک پالس ۱۰ میکروثانیهای درخواست میکند. |
| ارسال صوت | هشت سیکل با فرکانس ۴۰ کیلوهرتز | این عدد با فاصله زمانی دو اندازهگیری یکی نیست. |
| محدوده معرفیشده | ۲ تا ۴۰۰ سانتیمتر | بیرون این بازه در مثال معتبر حساب نمیشود؛ داخل بازه هم صحت تضمین نیست. |
| فاصله دو تحریک | بیش از ۶۰ میلیثانیه پیشنهاد شده | در برنامه ۱۰۰ میلیثانیه انتخاب کردهایم. |
منبع: دیتاشیت HC-SR04 با نام ELECFREAKS، میزبانیشده در SparkFun؛ همین فایل در بخش دانلود راهنمای رسمی Adafruit معرفی شده است. حدود مندرج در فایل به شرایط و هدف مناسب وابستهاند؛ عدد دقت تبلیغشده را تضمین همه بردهای بینام بازار ندانید.
اول نام و نسخه برد، سپس تغذیه، منطق ورودی/خروجی و نمودار زمانی را بخوانید. برخی بردهای جدید با ظاهر مشابه رابطهای اضافه دارند؛ این مقاله فقط رابط Trig/Echo سازگار با HC-SR04 معمولی را آموزش میدهد. وجود I2C، UART یا سازگاری مستقیم با ۳٫۳ ولت را از ظاهر حدس نزنید.
اتصال برق را قبل از جابهجایی سیمها قطع کنید. اگر USB و منبع خارجی همزمان وصل میشوند، مسیر تغذیه برد توسعه را بررسی کنید تا دو منبع به یکدیگر متصل نشوند.
| پایه ماژول | ESP32 کلاسیک در مثال | Arduino Uno در مثال |
|---|---|---|
| VCC | ۵ ولت تنظیمشده، مطابق نسخه ماژول | |
| GND | زمین مشترک منبع، سنسور و میکروکنترلر | |
| Trig | GPIO26 | D9 |
| Echo | از تقسیم مقاومتی به GPIO27؛ اتصال مستقیم ممنوع | D10 برای Uno با منطق ۵ ولت |
Echo نسخه معمولی، خروجی با منطق ۵ ولت است. آن را مستقیم به ESP32 متصل نکنید. راهنمای پایههای Adafruit کاهش سطح Echo و پذیرش Trig با منطق ۳ یا ۵ ولت را برای نمونه خود توضیح میدهد. نمونه واقعی را کنترل کنید.
HC-SR04 Echo ---- 10k (1%) ----+---- GPIO27 (ESP32)
|
15k (1%)
|
GND
HC-SR04 GND ------------------+---- ESP32 GNDدر این تقسیم، مقاومت ۱۰ کیلواهم بین Echo و گره ورودی و مقاومت ۱۵ کیلواهم بین همان گره و زمین قرار دارد. برای Echo دقیقاً ۵ ولت، خروجی محاسبهشده 5 × 15 / (10 + 15) = 3.0 V است. این طراحی مثال است، نه تضمین سطح همه ماژولها. سطح واقعی HIGH، تلرانس مقاومت، تغذیه و لبههای پالس باید بررسی شوند.
در دیتاشیت ESP32، جدول DC Characteristics حداقل HIGH برابر 0.75 × VDD آمده؛ در ۳٫۳ ولت، ۲٫۴۷۵ ولت میشود. بنابراین صرف «کمتر از ۳٫۳ بودن» کافی نیست و ولتاژ باید از حد HIGH نیز بالاتر باشد. ولتاژ ۵ ولت ورودی مجاز فرض نمیشود. میانگین مولتیمتر روی پالس، جای اندازهگیری دامنه با اسیلوسکوپ نیست.
شماره GPIOها انتخاب این مثالاند؛ برای C3، S3 یا بردی با پایههای مصرفشده باید عوض شوند. مستندات GPIO را همراه نقشه برد بخوانید. ترتیب فیزیکی پایهها را از نامهای چاپشده روی برد مشخص کنید، نه از رنگ سیم.
مقادیر قبلی را هنگام خطا بهعنوان قرائت تازه نمایش ندهید. اگر با برداشتن هدف همچنان عدد دارید، ممکن است بازتاب جسم دیگری دریافت شده باشد؛ آزمایش محیط را تغییر دهید و علت را جدا کنید.
کد زیر هر ۱۰۰ میلیثانیه یک تلاش انجام میدهد. سه نمونه معتبر پیاپی برای فیلتر لازم است و هر خطا فیلتر را پاک میکند. این برنامه کاملاً غیرمسدودکننده نیست: pulseIn تا پایان پالس یا timeout منتظر میماند. برای کار همزمان حساس به زمان، باید ثبت لبه یا سختافزار زمانسنج جداگانه طراحی شود.
#include <Arduino.h>
#if defined(ARDUINO_ARCH_ESP32)
const uint8_t TRIG_PIN = 26, ECHO_PIN = 27; // Classic ESP32 only
#else
const uint8_t TRIG_PIN = 9, ECHO_PIN = 10; // Arduino Uno
#endif
const uint32_t PERIOD_MS = 100; // Application choice; >60 ms between triggers
const unsigned long TIMEOUT_US = 30000;
const float SOUND_CM_PER_US = 0.0340f; // 340 m/s approximation, not compensated
float windowCm[3];
uint8_t validCount = 0, nextSlot = 0;
uint32_t lastSample = 0;
bool nearState = false;
void invalidReading(const __FlashStringHelper *reason) {
validCount = nextSlot = 0;
nearState = false; // Internal reset; output is UNKNOWN, not CLEAR.
Serial.print(F("INVALID,")); Serial.println(reason);
}
float median3(float a, float b, float c) {
if (a > b) { float t = a; a = b; b = t; }
if (b > c) { float t = b; b = c; c = t; }
if (a > b) { float t = a; a = b; b = t; }
return b;
}
void setup() {
Serial.begin(115200);
pinMode(TRIG_PIN, OUTPUT);
digitalWrite(TRIG_PIN, LOW);
pinMode(ECHO_PIN, INPUT); // ESP32: external voltage divider is mandatory.
Serial.println(F("HC-SR04: invalid does NOT mean zero distance or clear path."));
}
void loop() {
uint32_t now = millis();
if ((uint32_t)(now - lastSample) < PERIOD_MS) { delay(1); return; }
lastSample = now;
if (digitalRead(ECHO_PIN) == HIGH) { invalidReading(F("ECHO_ALREADY_HIGH")); return; }
digitalWrite(TRIG_PIN, LOW); delayMicroseconds(3);
digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
unsigned long us = pulseIn(ECHO_PIN, HIGH, TIMEOUT_US);
if (us == 0) { invalidReading(F("NO_COMPLETE_ECHO")); return; }
float cm = us * SOUND_CM_PER_US / 2.0f;
if (cm < 2.0f || cm > 400.0f) { invalidReading(F("OUTSIDE_EXAMPLE_RANGE")); return; }
windowCm[nextSlot] = cm;
nextSlot = (nextSlot + 1) % 3;
if (validCount < 3) ++validCount;
Serial.print(F("echo_us=")); Serial.print(us);
Serial.print(F(",raw_cm=")); Serial.print(cm, 1);
if (validCount < 3) { Serial.println(F(",WARMING_FILTER")); return; }
float filtered = median3(windowCm[0], windowCm[1], windowCm[2]);
if (filtered < 30.0f) nearState = true;
else if (filtered > 35.0f) nearState = false;
Serial.print(F(",median_cm=")); Serial.print(filtered, 1);
Serial.println(nearState ? F(",NEAR") : F(",NOT_NEAR"));
// Educational indicator only: no safety, braking or automatic pump control.
}دانلود برنامه اصلی، برنامه خام و راهنمای اتصال. هر فایل ino را در پوشه همنام خودش قرار دهید. آزمون این بسته در حد کامپایل نرمافزاری است؛ روی سنسور فیزیکی آزمایش نشده است.
ECHO_ALREADY_HIGH: پیش از تحریک، ورودی HIGH بوده است؛ بهجای تحریک دوباره، اندازهگیری نامعتبر گزارش میشود.NO_COMPLETE_ECHO: تابع صفر برگردانده است. این حالت، صفر سانتیمتر یا مسیر خالی نیست.OUTSIDE_EXAMPLE_RANGE: نتیجه تبدیل خارج بازه پذیرفتهشده مثال است.WARMING_FILTER: هنوز سه نمونه معتبر پیاپی نداریم؛ تصمیم فیلترشده منتشر نمیشود.NEAR و NOT_NEAR: فقط نتیجه مقایسه آموزشیاند، نه تشخیص ایمن مانع.طبق مستندات Arduino برای pulseIn، زمان پالس بر حسب میکروثانیه بازگردانده میشود و timeout بهصورت صریح قابل تنظیم است. ما ۳۰٬۰۰۰ میکروثانیه انتخاب کردهایم؛ این یک حد انتظار نرمافزاری است، نه مشخصه تضمینی سنسور.
فیلتر میانه از سه مقدار، مقدار وسط را انتخاب میکند و میتواند یک نمونه پرت منفرد را کماثر کند؛ خطای ثابت، هدف نامناسب و سیمبندی اشتباه را درمان نمیکند. آستانههای ۳۰ و ۳۵ سانتیمتر عمداً متفاوتاند تا در مرز تصمیم نوسان کمتری ایجاد شود. این فاصلهها انتخاب آموزشیاند و باید برای پروژه واقعی آزموده شوند. پس از خطا، خروجی معتبر قبلی حفظ نمیشود؛ برنامه دوباره سه نمونه معتبر میخواهد.
برای یک آزمون پیشنهادی، در فاصلههای ۲۰، ۵۰ و ۱۰۰ سانتیمتر از یک مبنای ثابت، در هر نقطه ۱۰ قرائت ثبت کنید. عدد مرجع، حداقل، حداکثر و تعداد خطاها را کنار هم بنویسید. این فاصلهها و تعداد تکرار، برنامه آزمایش پیشنهادیاند؛ هیچ نتیجهای از پیش برای آنها ادعا نمیکنیم.
اگر همه اعداد نزدیک هم ولی دور از مرجعاند، تکرارپذیری خوب لزوماً به معنی دقت خوب نیست. خطای مبدا، هندسه نصب و ضریب تبدیل را بررسی کنید. در مقابل، پراکندگی زیاد با عوضشدن زاویه هدف را با یک ضریب کالیبراسیون ثابت پنهان نکنید.
سرعت صوت با دما تغییر میکند. راهنمای Adafruit درباره سرعت صوت نمونه جبران وابسته به دما دارد. کد فعلی عمداً با فرض ثابت ۳۴۰ متر بر ثانیه کار میکند؛ اگر دقت بیشتری لازم است، ابتدا دمای نماینده مسیر صوت را بسنجید و روش جبران را جدا اعتبارسنجی کنید. برای شروع خواندن دما، آموزش DS18B20 در دسترس است.
| نشانه | بررسی عملی |
|---|---|
| همیشه نامعتبر | زمین مشترک، پایههای Trig/Echo، سطح ورودی بعد از تقسیم و هدف آزمایش را کنترل کنید. |
| فاصله با برداشتن هدف صفر میشود | کدی که صفر تابع را به فاصله تبدیل میکند اصلاح کنید؛ صفر تابع یعنی قرائت معتبر نداریم. |
| عدد با تغییر زاویه میپرد | آزمون را با هدف صاف و روبهرو تکرار کنید؛ بازتاب جانبی را بررسی کنید. |
| با اضافهشدن موتور رفتار عوض میشود | نخست موتور را از آزمایش حذف و تغذیه و زمین را بررسی کنید؛ متوسطگیری جای رفع علت نیست. |
| چند سنسور نتیجه نامطمئن میدهند | تنها یکی را فعال کنید و سپس زمانبندی نوبتی را با آزمون واقعی توسعه دهید. |
| Echo از ابتدا HIGH است | سیمبندی و نسخه برد را کنترل کنید؛ در صورت نیاز، با قطع امن تغذیه آزمون را از نو شروع کنید. |
برای دیدن پالس Trig و Echo از اسیلوسکوپ یا ورودی تحلیلگر منطقیِ سازگار با همان سطح ولتاژ استفاده کنید. واردکردن ۵ ولت به ورودی ابزار ۳٫۳ ولتی هم مجاز فرض نمیشود.
| معیار | HC-SR04 معمولی | VL53L0X |
|---|---|---|
| اصل سنجش | رفتوبرگشت صوت | زمان پرواز نور؛ فرستنده ۹۴۰ نانومتر |
| رابط این مقایسه | Trig/Echo و زمانسنجی پالس | I2C و خواندن نتیجه پردازششده |
| نکته اتصال | برای ESP32 سطح Echo باید سازگار شود. | تغذیه و مبدل سطح روی برد واسط بررسی شود؛ تراشه خام با ماژول یکی نیست. |
| روش تصمیم | با هدف و محیط واقعی خودتان بیازمایید. | برای همان هدف، نتیجه و وضعیت خطا را کنار آزمایش اول بگذارید. |
مرجع ویژگیهای VL53L0X، صفحه رسمی ST است. برای سیمکشی و کد آن، آموزش مستقل VL53L0X را ببینید. صرف مقایسه حداکثر برد اسمی، برنده همه کاربردها را تعیین نمیکند. ابتدا اندازه هدف، محیط، فاصله مورد نیاز و رفتار هنگام خطا را مشخص کنید.
برد را محکم نصب کنید و جلوی دو مبدل را نپوشانید. شکل هدف و محل نصب باید بخشی از برنامه آزمون باشند. برد معمولی را برای زیر آب یا محیط خیس مناسب فرض نکنید؛ برای سطح مخزن، حفاظت محیطی و محدودیت کاربرد باید جداگانه تأیید شود. در پروژه چندحسگری، تداخل را با فعالکردن نوبتی و ثبت نتایج بررسی کنید، نه با فرض اینکه همه پالسها مستقلاند.
اگر گزارش را با BLE میفرستید، علاوه بر فاصله، معتبر بودن و زمان آخرین اندازهگیری را نیز ارسال کنید؛ آموزش پروژههای مقدماتی BLE شروع مناسبی است. برای تشخیص صرف حرکت، PIR مسئله متفاوتی را حل میکند و خروجی آن جای فاصله نیست.
وضعیت زیر در ۱۰ سپتامبر ۲۰۲۶ / ۱۹ شهریور ۱۴۰۵ بررسی شد و تضمین موجودی آینده نیست. قیمت ثابت درج نمیکنیم. هر دو لینک به صفحه HC-SR04 هستند؛ نسخه دقیق برد ارسالی را پیش از سفارش تأیید کنید.
هنگام بررسی: موجود در انبار و قابل افزودن به سبد خرید. پرسشها و تجربههای دارای نشان خریدار، شاهد استفاده عملیاند؛ آمار فروش از آنها استخراج نکردهایم.
هنگام بررسی: ناموجود. برای پیگیری همان مدل معرفی شده، نه خرید فوری کالای موجود.
در بازار، چینش قطعات پشت برد و قابلیتهای نسخهها تغییر میکند. نام HC-SR04 بهتنهایی تضمین نمیکند تصویر، ولتاژ یا رابطهای اضافی تمام فروشندگان یکسان باشد. لینک US-100، SRF05 یا مدل ضدآب را به جای این محصول معرفی نکردهایم. منابع فروشگاهی فقط برای وضعیت خرید و شواهد بازار استفاده شدهاند.
برای HC-SR04 معمولی خیر؛ Echo با منطق ۵ ولت است و باید با تقسیم ولتاژ یا مبدل مناسب به سطح سازگار تبدیل شود.
خیر. در این برنامه صفر تابع یعنی پالس کامل در زمان انتظار دریافت نشده و قرائت نامعتبر است، نه فاصله صفر یا مسیر خالی.
خیر. برنامه فاصله زمانی نمونهها را کنترل میکند، اما pulseIn هنگام انتظار برای پالس میتواند اجرای حلقه را تا timeout متوقف کند.
خیر. فیلتر میتواند اثر یک نمونه پرت را کاهش دهد، ولی خطای ثابت، هندسه نامناسب و اتصال اشتباه را اصلاح نمیکند.
خیر. اصل سنجش و رابط این دو متفاوت است؛ انتخاب باید با هدف، محیط و آزمون خطاهای پروژه انجام شود، نه فقط حداکثر برد اسمی.
فاصلهسنج مفید فقط عدد تولید نمیکند؛ باید هنگام نبود داده معتبر هم رفتار روشنی داشته باشد. ابتدا سطح Echo و زمان خام را بررسی کنید، سپس فیلتر و تصمیمگیری را اضافه کنید. در مسیر فاصله و سطح و راهنمای سنسورها میتوانید موضوعهای مرتبط را ادامه دهید.
متن و مثال آموزشی: LCENJ. کد برای کامپایل روی ESP32 کلاسیک و Arduino Uno بررسی میشود؛ آزمایش سختافزاری انجام نشده و نتیجه اندازهگیری واقعی ادعا نشده است.
برای یک مسیر منظم از مبانی تا انتخاب و آزمون حسگر، دوره سنسورها در ۷ قدم را دنبال کنید.