افزایش دقت فاصله سنج آردوینو

Ratings
(0)

 

 طبق مشخصات فنی، سنسور PING برای اشیائی که در فاصله ای بین 2 سانتی متر تا 3 متر قرار دارند دقیق است. (ضمنا علت این امر، طول پالسی است که تولید می شود. حداقل طول 115 میکروثانیه است و حداکثر طول 18.5 میلی ثانیه است). با روش فعلی که به کار گرفته ایم، از دقت در آن هیچ بهره ای نمی بریم زیرا تمام محاسبات با استفاده از اعداد صحیح انجام می شود. ما تنها می توانیم فاصله را با دقت یک سانتی متر اندازه بگیریم. برای اینکه بتوانیم از میلی متر استفاده کنیم، باید از اعداد ممیز شناور(floating-point) استفاده کنیم.

معمولاً، این ایده ی خوبی است که از عملیات اعداد صحیح(integer ) استفاده کنیم، زیرا در مقایسه با کامپیوترهای عادی، ظرفیت های حافظه و CPU آردوینو به شدت محدود می شوند و محاسباتی که حاوی اعداد ممیز-شناور هستند، برای ما  گران تمام می شوند.  اما گاهی اوقات لازم است تا از اعداد ممیز-شناور بسیار دقیق استفاده کنیم و آردوینو به خوبی از آنها پشتیبانی می کند. ما اکنون قصد داریم از این اعداد برای بهبود بخشیدن به پروژه ی خود استفاده کنیم:

const unsigned int PING_SENSOR_IO_PIN = 7;
const unsigned int BAUD_RATE = 9600;
const float MICROSECONDS_PER_CM = 29.155;
const float MOUNTING_GAP = 0.2;
const float SENSOR_OFFSET = MOUNTING_GAP * MICROSECONDS_PER_CM * 2; 

void setup() {
  Serial.begin(BAUD_RATE);
}
void loop() {
  const unsigned long duration = measure_distance();
  if (duration == 0)
    Serial.println("Warning: We did not get a pulse from sensor.");
  else
    output_distance(duration);
}

const float microseconds_to_cm(const unsigned long microseconds) {
  const float net_distance = max(0, microseconds - SENSOR_OFFSET);
  return net_distance / MICROSECONDS_PER_CM / 2;
}


const unsigned long measure_distance() {
  pinMode(PING_SENSOR_IO_PIN, OUTPUT);
  digitalWrite(PING_SENSOR_IO_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(PING_SENSOR_IO_PIN, HIGH);
  delayMicroseconds(5);
  digitalWrite(PING_SENSOR_IO_PIN, LOW);
  pinMode(PING_SENSOR_IO_PIN, INPUT);
  return pulseIn(PING_SENSOR_IO_PIN, HIGH);
}

void output_distance(const unsigned long duration) {
  Serial.print("Distance to nearest object: ");
  Serial.print(microseconds_to_cm(duration)); 
  Serial.println(" cm");
}

این کد در آدرس زیر قرار دارد:

InputDevices/Ultrasonic/Float/Float.ino

 

 این برنامه با  اولین برنامه ای که نوشتیم خیلی تفاوت نمی کند. ابتدا از مقدار دقیق تر 29.155 برای تعداد میکروثانیه ای که طول می کشد تا صدا 1 سانتی متر حرکت کند ، استفاده می کنیم.

 

جمله ی زیر بیشتر بررسی شود:

علاوه بر این، اکنون در محاسبه ی فاصله، یک اختلاف(gap) بین سنسور و کیت آن وجود دارد که اهمیت دارد.اگر ما سنسور را روی یک برد برد قرار دهیم، معمولا یک اختلاف کوچک بین سنسور و لبه ی برد برد وجود دارد. این اختلاف در خط 5 تعریف شده است و بعداً در محاسبه ی فاصله مورد استفاده قرار خواهد گرفت. این اختلاف با سانتی متر اندازه گیری شده است و در 2 ضرب شده است زیرا صوت یکبار می رود و یکبار برمی گردد.

 

متد loop اکنون تمیز تر به نظر می رسد، زیرا عملکرد اصلی برنامه در چند تابع قرار گرفته است. منطق کلی کنترل سنسور در متد measure_distance قرار گرفته است و متد output_distance در مورد بیرون دادن مقادیر در پورت سریال(serial port) فعالیت می کند.

 در متد microseconds_to_cm تغییرات بزرگی صورت گرفته است. این متد اکنون یک مقدار float را برمی گرداند و اختلاف سنسور را از فاصله ی محاسبه شده تفریق می کند(کم می کند). برای اینکه مطمئن شویم که مقادیر را منفی نکرده ایم، از تابع max استفاده می کنیم.

اکنون برنامه را کامپایل و آپلود کنید و باید در پنجره ی سریال مانیتور(serial monitor) چیزی شبیه زیر را مشاهده کنید: 

Distance to nearest object: 17.26 cm
Distance to nearest object: 17.93 cm
Distance to nearest object: 17.79 cm
Distance to nearest object: 18.17 cm
Distance to nearest object: 18.65 cm
Distance to nearest object: 18.85 cm

 همان طور که مشاهده می کنید، دقت محاسبات نسبت به قبل بسیار بیشتر شده است. اگر از قبل  با اعداد ممیز شناور(floating-point) در یک زبان برنامه نویسی، کار کرده باشید، ممکن است از خودتان بپرسید که چرا آردوینو به طور اتوماتیک این اعداد را به دو رقم اعشار گرد می کند؟ راز این کار در متد print از کلاس Serial قرار دارد.

از نسخه های اخیر پلتفرم آردوینو، این متد برای تمام انواع داده های امکان پذیر، کار می کند و وقتی که یک متغیر float را دریافت می کند، قبل از اینکه آن را در خروجی نشان دهد، آن را به دو رقم اعشار گرد می کند. ما می توانیم تعداد رقم های اعشار را مشخص کنیم. بعنوان مثال دستور زیر:

Serial.println(3.141592, 4);

 مقدار زیر را برمی گرداند:

3.1416

تنها خروجی(output ) تحت تاثیر این متد قرار می گیرد و در داخل، این عدد هنوز یک متغیر float است. به هر حال، در بیشتر بردهای آردوینو، مقادیر float و double فعلا مانند یکدیگر هستند. تنها در آردوینو Due، مقادیر double دقیق تر از مقادیر float هستند.  بنابراین، چقدر هزینه دارد که ما از متغیرهای float استفاده کنیم؟ مصرف حافظه ی(memory ) آنها، 4 بایت است و  آنها به اندازه ی متغیرهای long حافظه مصرف می کنند. از طرف دیگر، محاسبات ممیز شناور(floating-point) نسبتا گران تمام می شوند و باید در بخش هایی از نرم افزار که بحران زمانی(time-critical) وجود دارد، از استفاده ی آنها اجتناب شود. بزرگترین هزینه ی استفاده از اعداد ممیز شناور، توابع کتابخانه ای اضافی هستند که باید برای پشتیبانی از float ها به برنامه اضافه شوند. ممکن است دستور Serial.print(3.14) بی ضرر به نظر برسد اما سایز برنامه ی ما را فوق العاده افزایش می دهد. برای تست کردن این موضوع، در کدهای بالا خط 37 را کامنت کنید و دوباره برنامه را کامپایل کنید تا نتیجه را مشاهده کنید. ممکن است برنامه دیگر به درستی کار نکند، اما ما می توانیم مشاهده کنیم که چگونه این دستور بر روی سایز برنامه تاثیر می گذارد. با تست فعلی من، اگر از float برای Serial.print استفاده نکنیم 3002 بایت فضا مورد نیاز خواهد بود و در غیر این صورت به 5070 بایت حافظه نیاز خواهیم داشت.تفاوت این دو مقدار می شود، 2068 بایت!

 

 ما می توانیم با تبدیل مقادیر float به اعداد صحیح(integers) قبل از اینکه آنها را به اتصالات سریال(serial connection) بفرستیم، از هدر رفتن فضای حافظه ی زیادی جلوگیری کنیم. برای اینکه بتوانید مقادیر با دقت دو رقم اعشار، را انتقال دهید، آنها را در 100 ضرب کنید و فراموش نکنید که در سمت دریافت داده، آنها را بر 100 تقسیم کنید. ما در این مورد (including rounding)) بعدا صحبت خواهیم نمود.

ص86

 {module کمک نقدی به نویسنده}

  • بازدید: 1027

نوشتن دیدگاه

لطفا نظرات خود را بیان کنید. به سوالات در سریع ترین زمان پاسخ داده خواهد شد.اما به نکات زیر توجه کنید:
1. سعی کنید نظرات شما مرتبط با مقاله ی مورد نظر باشد، در غیر این صورت پاسخ داده نخواهد شد.
2. سوالات خود را به صورت کوتاه بیان کنید و از پرسیدن چند سوال به طور همزمان خودداری کنید.
3. سوال خود را به طور واضح بیان کنید و از کلمات مبهم استفاده نکنید.

ارسال