تعیین مقادیر مینیمم و ماکزیمم سنسور
دنیای فیزیکی اغلب از کامل بودن به دور است. این موضوع برای داده هایی که اکثر سنسورها منتشر می کنند نیز صحت دارد و شتاب سنج ها نیز از این قاعده مستثنی نیستند. این سنسورها در حداقل و حداکثر مقادیر تولیدی خود کمی متفاوت هستند. این سنسورها ممکن است حتی اگر ما آنها را حرکت نداده باشیم، مقادیر خروجی خود را تغییر دهند و یا اینکه آنها ممکن است به درستی مقادیر خروجی خود را تغییر ندهند. در این بخش، ما می خواهیم مقادیر مینیمم و ماکزیمم سنسور مورد نظر را مشخص کنیم. پیدا کردن مقادیر مینیمم و ماکزیمم سنسور آسان است، اما به راحتی نمی توان آن را اتوماتیک و خودکار کرد. ما باید دائماً خروجی سنسور را به هنگام حرکت دادن آن قرائت کنیم. برنامه ای که این کار را انجام می دهد، به صورت زیر است:
const unsigned int X_AXIS_PIN = A2;
const unsigned int Y_AXIS_PIN = A1;
const unsigned int Z_AXIS_PIN = A0;
const unsigned int BAUD_RATE = 9600;
int min_x, min_y, min_z;
int max_x, max_y, max_z;
void setup() {
Serial.begin(BAUD_RATE);
min_x = min_y = min_z = 1000;
max_x = max_y = max_z = -1000;
}
void loop() {
const int x = analogRead(X_AXIS_PIN);
const int y = analogRead(Y_AXIS_PIN);
const int z = analogRead(Z_AXIS_PIN);
min_x = min(x, min_x); max_x = max(x, max_x);
min_y = min(y, min_y); max_y = max(y, max_y);
min_z = min(z, min_z); max_z = max(z, max_z);
Serial.print("x(");
Serial.print(min_x);
Serial.print("/");
Serial.print(max_x);
Serial.print("), y(");
Serial.print(min_y);
Serial.print("/");
Serial.print(max_y);
Serial.print("), z(");
Serial.print(min_z);
Serial.print("/");
Serial.print(max_z);
Serial.println(")");
}
ما در کدهای بالا، متغیرهایی برای مقادیر مینیمم و ماکزیمم برای هر سه محور تعریف کرده ایم و سپس آنها را با اعدادی که قطعاً از محدوده ی(range) سنسور خارج هستند، (یعنی با 1000 و 1000-) مقدار دهی اولیه(initialize ) می کنیم. در تابع loop نیز ما به طور دائمی شتاب را برای هرسه محور اندازه گیری می کنیم و بر این اساس مقادیر مینیمم و ماکزیمم را تنظیم می کنیم.
اسکچ(sketch) را کامپایل و آپلود کنید، سپس برد برد را به همراه سنسور در تمامی جهت ها حرکت دهید و سپس آن را به دور تمام محورها(axes) حرکت دهید. سعی کنید آن را به آرامی و سپس به سرعت حرکت دهید، و همین کار را به دور محورها نیز انجام دهید. وقتی که دارید بردبرد را حرکت می دهید و می چرخانید مراقب باشید تا اتصالات به یکباره قطع نشوند. پس از مدت کوتاهی، مقادیر مینیمم و ماکزیمم ثابت(stabilize) می شوند و باید یک خروجی شبیه زیر را داشته باشیم:
x(247/649), y(253/647), z(278/658)
این مقادیر را یادداشت کنید، زیرا بعداً به آنها نیاز خواهید داشت و احتمالا وقتی که دارید با سنسور خودتان آزمایش انجام می دهید به آنها نیازمند خواهید شد.
ما به جای اینکه داده های شتاب را مستقیماً برگردانیم(returning )، آخرین قرائت ها را جمع آوری می کنیم و میانگین را برمی گردانیم. به این شیوه تغییرات کوچک متعادل می شوند. کدها به صورت زیر است:
const unsigned int X_AXIS_PIN = 2;
const unsigned int Y_AXIS_PIN = 1;
const unsigned int Z_AXIS_PIN = 0;
const unsigned int NUM_AXES = 3;
const unsigned int PINS[NUM_AXES] = {
X_AXIS_PIN, Y_AXIS_PIN, Z_AXIS_PIN
};
const unsigned int BUFFER_SIZE = 16;
const unsigned int BAUD_RATE = 9600;
int buffer[NUM_AXES][BUFFER_SIZE];
int buffer_pos[NUM_AXES] = { 0 };
void setup() {
Serial.begin(BAUD_RATE);
}
int get_axis(const int axis) {
delay(1);
buffer[axis][buffer_pos[axis]] = analogRead(PINS[axis]);
buffer_pos[axis] = (buffer_pos[axis] + 1) % BUFFER_SIZE;
long sum = 0;
for (unsigned int i = 0; i < BUFFER_SIZE; i++)
sum += buffer[axis][i];
return round(sum / BUFFER_SIZE);
}
int get_x() { return get_axis(0); }
int get_y() { return get_axis(1); }
int get_z() { return get_axis(2); }
void loop() {
Serial.print(get_x());
Serial.print(" ");
Serial.print(get_y());
Serial.print(" ");
Serial.println(get_z());
}
مثل همیشه، ما ابتدا برخی ثابت ها(constants) را برای پین هایی که مورد استفاده قرار داده ایم را تعریف کرده ایم. این دفعه، ما یک ثابت به نام NUM_AXES را نیز تعریف کرده ایم که دربر دارنده ی تعداد محورهایی است که داریم محاسبه می کنیم. همچنین یک آرایه به نام PINS داریم که حاوی لیستی از پین هایی است که مورد استفاده قرار می دهیم. این به ما کمک می کند تا کدهای ما بعداً به طور کلی تری تلقی شوند.
در خط 10، ما بافرهایی(buffers ) را برای تمام محورها تعریف می کنیم. این بافرها با داده های سنسور که آنها را اندازه گیری می کنیم، پر می شوند؛ بنابراین ما می توانیم مقادیر میانگین را وقتی که به آنها نیاز داریم محاسبه کنیم. ما باید در هر بافر، موقعیت فعلی(current position) خود را ذخیره کنیم؛ از این رو، در خط 11 ما یک آرایه از موقعیت های بافرها را تعریف کرده ایم.
تابع setup تنها پورت سریال(serial port) را مقدار دهی اولیه(initializes ) می کند؛ عمل واقعی، در متد get_axis اتفاق می افتد. این متد، با یک وقفه ی(delay ) کوتاه شروع می شود، تا به آردوینو کمی فرصت دهد تا بین پین های آنالوگ سوئیچ کند؛ در غیر این صورت ممکن است داده های غیرمفیدی دریافت کنیم. سپس این متد، شتاب را برای محورهایی(axis ) که به آن داده ایم قرائت می کند و آن را در موقعیت(position) بافر فعلی، که به محور مورد نظر تعلق دارد، ذخیره می کند. سپس موقعیت(position ) بافر را افزایش می دهد و وقتی که بافر به انتهای خود رسید، آن را به 0 تنظیم می کند. در نهایت ما مقدار میانگین(average value) داده هایی که تاکنون فراهم شده است را برای محور فعلی، برمی گردانیم(return می کنیم).
این ترفند تمام شد و ساختار داده ای که ما ساخته ایم ، بافر چرخشی(circular buffer) نامیده می شود. برای مشاهده ی تاثیر آن، سنسور را دست نخورده روی میز خود قرار دهید و برنامه را با سایزهای بافر متفاوتی اجرا کنید. اگر به سنسور دست نزنیم، نباید انتظار داشته باشیم که خروجی برنامه تغییر کند. اما اگر ما BUFFER_SIZE را به 1 تنظیم کنیم، به سرعت تغییراتی را مشاهده خواهیم کرد. اما این تغییرات در صورتی که بافر به اندازه ی کافی بزرگ باشد، ناپدید خواهند شد.
اکنون داده های شتابی که ما اندازه گیری می کنیم، به اندازه ی کافی دقیق است، به طوری که می توانیم با آنها یک کنترلر بازی(game controller) بسازیم که با حرکات غیر منتظره کاربران را آزار نخواهد داد.
{module کمک نقدی به نویسنده}
- بازدید: 614
1. سعی کنید نظرات شما مرتبط با مقاله ی مورد نظر باشد، در غیر این صورت پاسخ داده نخواهد شد.
2. سوالات خود را به صورت کوتاه بیان کنید و از پرسیدن چند سوال به طور همزمان خودداری کنید.
3. سوال خود را به طور واضح بیان کنید و از کلمات مبهم استفاده نکنید.